文章出处:http://www.jianshu.com/p/1008f9803759#

先看最终效果:

- - -

绘画这个纯属周末雨天无聊,这里使用的都是Core Graphics上很基本的几个方法,对新手(我也是新手)来说还是有帮助的。下面说下这个绘制过程。

0. 设置背景色

1. 绘制绿色椭圆

2. 绘制绿色三角形

3. 绘制眼睛

4. 绘制白色椭圆

5. 绘制白色三角形

6. 绘制眼睛

7. 就这么简单

_ _ _

那么,省去创建project的步骤之后我们要做的就是自定义个UIView子类,我们就将它命名为`WechatView`,然后在storyboard上拖动一个`UIView`到视图控制器上。

接着,为了在绘制过程中能不需要每次都编译,我们可以使用iOS7之后的一个新特性 `IB_DESIGNABLE` 来时时看到我们的绘画过程。说到 `IB_DESIGNABLE` 就自然的会联想到 `IBInspectable`,先浅陋的介绍一下这两个的作用。首先是 `IB_DESIGNABLE`,如刚才所说,它可以让我们时时的看到我们的绘制过程,大大的省去了我们编译的时间,是iOS7上一个超赞的新特性。然后是 `IBInspectable`,它是添加在属性上的,在属性上添加上它我们就可以在Xcode的右边的*Show the Attributes inspector*上看到,并可以自定义这些值(当然,并不是所有的类习惯都支持的,具体有哪些,需要的时候试试便知哈)。

回到正题,现在我们只需要将 `IB_DESIGNABLE` 添加到`WechatView` 的头文件上即可(当然,你想添加到.m文件上编译器也不反对)。然后,在这里就添加一个用处不大的属性bkColor作为背景颜色,如下代码:

IB_DESIGNABLE

@interface WechatView : UIView

@property(nonatomic, assign)IBInspectable UIColor *bkColor;

@end

这样,我们就可以在点击storyboard后,选择*Show the Identity inspector*上看到下图:

在*Show the Attributes inspector*上看到下图:

现在改变一下bkColor,将它改为灰色。

改后当然是看不到视图改变的,我们得真正的为 `backgoundColor` 这个属性赋值;或者使用Core Graphices来填充背景。方法一中如果想时时看到改变效果,我们可以添加如下代码:

- (void)prepareForInterfaceBuilder {

[super prepareForInterfaceBuilder];

self.backgroundColor = self.bkColor;

}

代码刚上,效果即可见哈,爽

`prepareForInterfaceBuilder` 这个方法是iOS8之后才有的,它就是提供给我们试试查看效果的,但是它只是在当你的view准备被绘制在*Interface Builder*时被执行,换句话说就是程序运行时它是不被调用的。==command+r==运行下程序我们就可以发现,这是的view背景并不是刚才所看到的灰色。说明`prepareForInterfaceBuilder`确实没有被调用。(我们可以通过这个方法,省去编译时间来看我们的绘制效果,然后再将代码移到我们所要的位置)。这个方法就说到这。

填充背景

还有方法二,也是接下来我们要用到的方法:使用Core Graphices来填充背景。将前面的代码注释掉,然后添加如下代码:

- (void)drawRect:(CGRect)rect {

/*0. 填充背景*/

//将当前context的颜色填充为bkColor

[self.bkColor setFill];

//填充颜色到当前的context上,大小为rect

CGContextFillRect(context, rect);

}

同样,可以看到`WechatView`的背景变成了灰色。这样就算开始了第0步绘画。

绘制绿色椭圆

第1步是开始绘制绿色椭圆,在以上的代码基础上继续添加如下代码:

//绘制的最小宽度

CGFloat minWidth = MAX(160, rect.size.width);

//定义绿色椭圆位置和大小

CGFloat greenX = 10;

CGFloat greenY = 10;

CGFloat greenCircleWidth = minWidth/1.5;

CGFloat greenCircleHeight = 21.0/24 * greenCircleWidth;

CGFloat gcW = greenCircleWidth;

CGFloat gcH = greenCircleHeight;

//1. 绘制绿色椭圆

UIColor *greenColor = RGB(125, 225, 73, 1);

//将当前context的颜色填充为greenColor

[greenColor setFill];

//绘制并填充椭圆

CGContextFillEllipseInRect(context, CGRectMake(greenX, greenY, greenCircleWidth, greenCircleHeight));

完成了第1步,效果见图:

绘制绿色三角形

第2步:绘制绿色三角形。通过观察微信的icon,计算,微调,我们可以添加以下的代码来绘制这个三角形:

//2. 画三角形

//椭圆左边焦点

CGFloat greenCircleFocusLeft = gcW/2-sqrt(pow(gcW/2, 2)-pow(gcH/2, 2));

//椭圆右边焦点

CGFloat greenCircleFocusRight = gcW/2+sqrt(pow(gcW/2, 2)-pow(gcH/2, 2));

CGFloat gcFL = greenCircleFocusLeft;

CGFloat gcFR = greenCircleFocusRight;

//眼睛大小

CGFloat eyesWidth1 = gcW/7.5;

//2. 画三角形

CGPoint points[] = {

CGPointMake(gcFL-eyesWidth1, greenY + gcH + (gcFL-eyesWidth1)/12-10),

CGPointMake(greenX+gcW/2+40, 1.2*(greenX+gcW/2) + greenY),

CGPointMake(gcFL+10, 1.8*gcFL + greenY)};

CGContextAddLines(context, points, 3);

CGContextClosePath(context);

//CGContextStrokePath(context);

CGContextFillPath(context);

三角形的三个点的计算花了我不少时间,但是这不是重点,重点是其实很简单的问题我却傻X的花了很长时间哈,而且最终还只是凑合的,不是最优解。取消`CGContextStrokePath(context);`这句的注释,我们可以看到下图:

注释掉后即可看到:

绘制眼睛

第3步:绘制眼睛。眼睛的位置取的是椭圆焦点的位置,而且绘制后看起来还挺对的。眼睛无非是两个黑色的圆形。如下:

//3. 画眼睛(圆)

[RGB(45, 49, 32, 1) setFill];

CGContextFillEllipseInRect(context, CGRectMake(greenX + gcFL, greenY+gcH/4, eyesWidth1, eyesWidth1));

CGContextFillEllipseInRect(context, CGRectMake(greenX + gcFR-eyesWidth1, greenY+gcH/4, eyesWidth1, eyesWidth1));

然后就是这样了:

绘制白色icon

第4,5,6步跟1,2,3步基本是一样的,只是位置不同而已。

//4. 画白色椭圆

CGFloat wcX = greenX + gcW / 2;

CGFloat wcY = greenY + gcH / 2;

CGFloat wcW = gcW * 0.8;

CGFloat wcH = gcH * 0.8;

CGFloat whiteCircleFocusLeft = wcW/2-sqrt(pow(wcW/2, 2)-pow(wcH/2, 2));

CGFloat whiteCircleFocusRight = wcW/2+sqrt(pow(wcW/2, 2)-pow(wcH/2, 2));

CGFloat wcFL = whiteCircleFocusLeft;

CGFloat wcFR = whiteCircleFocusRight;

CGFloat eyesWidth2 = wcW/7.5;

UIColor *whiteColor = RGB(251, 251, 251, 1);

[whiteColor setFill];

CGContextFillEllipseInRect(context, CGRectMake(wcX, wcY, wcW, wcH));

//5. 画白色三角形

CGPoint whiteTrianglePoints[] = {

CGPointMake(wcFR+eyesWidth2/4+wcX, wcY + wcH + (wcFL-eyesWidth2/4)/4),

CGPointMake(wcX+wcW/2, 0.9*(wcX+wcW/2)),

CGPointMake(wcFR+eyesWidth2, 0.9*wcFR + wcY)};

CGContextAddLines(context, whiteTrianglePoints, 3);

CGContextClosePath(context);

CGContextFillPath(context);

//6. 画眼睛(圆)

[RGB(60, 64, 49, 1) setFill];

CGContextFillEllipseInRect(context, CGRectMake(wcX + wcFL, wcY + wcH/4, eyesWidth2, eyesWidth2));

CGContextFillEllipseInRect(context, CGRectMake(wcX + wcFR - eyesWidth2, wcY + wcH/4, eyesWidth2, eyesWidth2));

OK,现在就长这样了,咋一看还是挺像的哈。

添加阴影

下面我们再添加一些细节上的东西。比如我们发现少了阴影,还有微信的icon上的三角形是圆角的。首先是阴影:在`CGFloat minWidth = MAX(160, rect.size.width);`这句之上加上下面的代码:

//阴影

CGContextSetShadowWithColor(context, CGSizeMake(-0.5, 0.5), 6, [UIColor blackColor].CGColor);

阴影是加上了,但是并不是我们想要的效果。怎样才能让它只是在边缘上加阴影呢?也很简单,继续在刚才添加的语句下添加:

CGContextBeginTransparencyLayer(context, nil);

搞定,感觉还行哈,不过眼睛的阴影好像也没了。试试用同样的方法看能不能解决:在第3步画眼睛之前添加:

CGContextEndTransparencyLayer(context);

//为绿色椭圆的眼睛添加阴影

CGContextSetShadowWithColor(context, CGSizeMake(-0.5, 0.5), 2, [UIColor blackColor].CGColor);

然后在第3步画完眼睛之后添加:

CGContextBeginTransparencyLayer(context, nil);

再然后在第6步画眼睛之前添加上:

//为白色椭圆的眼睛添加阴影

CGContextSetShadowWithColor(context, CGSizeMake(-0.5, 0.5), 2, [UIColor blackColor].CGColor);

这样说有点乱,注意到了:`CGContextBeginTransparencyLayer(context, nil)` 和 `CGContextEndTransparencyLayer(context)` 是成对出现的,从函数名称可以知道它们的作用分别是开始一个透明的layer和结束一个透明的layer。而夹在它们中间的绘图操作在指定的context上被合成到一个完全透明的背景(在context中作为一个分离的目标缓冲区)。这个操作会保持context原有的裁剪区域。调用了`Begin`之后除了1.全局的透明度被设置为1;2.阴影被屏蔽外,其他的都不变。这样解释后,上面的代码应该可以理解了。现在我们的icon看起来是这样的:

圆角三角形

最后,解决下圆角三角形的问题:回到第2步,将`CGContextFillPath(context);`注释,并添加以下代码:

CGContextSetLineJoin(context, kCGLineJoinRound);

CGContextSetLineWidth(context, 4);

CGContextSetStrokeColorWithColor(context, greenColor.CGColor);

CGContextDrawPath(context, kCGPathFillStroke);

然后同理在第5步画白色三角形上注释`CGContextFillPath(context);`,并添加以下代码:

CGContextSetLineJoin(context, kCGLineJoinRound);

CGContextSetLineWidth(context, 3);

CGContextSetStrokeColorWithColor(context, whiteColor.CGColor);

CGContextDrawPath(context, kCGPathFillStroke);

好了,废话说完了,也算是完成了,最终效果:

实际上,微信的icon的颜色还是一个渐变的,在这里就不继续研究了,要实现渐变可以用`CGContextDrawLinearGradient(CGContextRef context, CGGradientRef gradient, CGPoint startPoint, CGPoint endPoint, CGGradientDrawingOptions options)`或`CGContextDrawRadialGradient(CGContextRef context, CGGradientRef gradient, CGPoint startCenter, CGFloat startRadius, CGPoint endCenter, CGFloat endRadius, CGGradientDrawingOptions options)`这两个函数。

bug 修复

command+r 编译+运行以下(现在才需要编译,这也太好了吧),然后发现成功的crash了。

什么原因?好吧,我把属性定义成 `assign` 了(低级错误),改成`strong` ,问题解决。

结束语

以上就是我绘制的整个编码过程,绘制微信icon实际上就用了core graphics的几个基本功能,希望能对初学者有所帮助,说错的地方也希望能得到指点哈~~

源码地址:https://github.com/linshaolie/blog/tree/master/DrawWechatIcon

转载于:https://www.cnblogs.com/panyuluoye/p/4954972.html

【转】使用Core Graphics绘画一个山寨微信icon相关推荐

  1. 使用Core Graphics绘画一个山寨微信icon

    使用Core Graphics绘画一个山寨微信icon 最终效果: 绘画这个纯属周末雨天无聊,这里使用的都是Core Graphics上很基本的几个方法,对新手(我也是新手)来说还是有帮助的.下面说下 ...

  2. iOS开发--Core Graphics绘图

    一. Core Graphics简介 Core Graphics是一个基于C的绘图专用的API族,它经常被称为QuartZ或QuartZ 2D,是一个二维绘图引擎,同时支持iOS和Mac系统.它提供了 ...

  3. 核心绘图——Core Graphics

    一. Core Graphics简介 Core Graphics是一个基于C的绘图专用的API族,它经常被称为QuartZ或QuartZ 2D,是一个二维绘图引擎,同时支持iOS和Mac系统.它提供了 ...

  4. Core Graphics

    Core Graphics入门 想必每个第一次接触Core Graphics的开发者都被无数的API.混乱的代码逻辑折腾得头疼不已,甚至望而却步.即使是绘制一个简单的矩形也看上去非常繁琐.本文换一个角 ...

  5. Core Graphics 定制UIVIew 处理图片

    许多UIView的子类,如UIButton或UILabel,它们的形状都是系统固定的.但是,对于一些特殊的情况,我们需要绘制产品狗想要的图形.那么等待我们的只有两个选择:第一,可以使用UIImageV ...

  6. iOS图形编辑之Core Graphics

    Core Graphics Framework是一套基于C的API框架,使用了Quartz作为绘图引擎.它提供了低级别.轻量级.高保真度的2D渲染.该框架可以用于基于路径的绘图.变换.颜色管理.脱屏渲 ...

  7. .NET Core 3.0 一个 jwt 的轻量角色/用户、单个API控制的授权认证库

    作者:痴者工良(朋友合作原创) 来源: https://www.cnblogs.com/whuanle/p/11743406.html 目录 说明 一.定义角色.API.用户 二.添加自定义事件 三. ...

  8. 使用 Core Graphics 绘制基本形状

    作者:Arthur Knopper,原文链接,原文日期:2015-08-31 译者:lfb_CD:校对:千叶知风:定稿:shanks Core Graphics是Cocoa和Cocoa Touch所共 ...

  9. iOS绘图UIBezierPath 和 Core Graphics框架

    前言 iOS系统本身提供了两套绘图的框架,即UIBezierPath 和 Core Graphics.而前者所属UIKit,其实是对Core Graphics框架关于path的进一步封装,所以使用起来 ...

最新文章

  1. 使用MrBayes构建贝叶斯系统发育树【实践】
  2. 一个关于nvarchar字段排序,中英文混合排序的问题
  3. 【python 学习】知识点日记
  4. JDBC有这一篇就够了(万字JDBC附代码详解)
  5. linux虚拟网桥配置nat,使用NAT在Proxmox VE 6上创建专用网桥的方法
  6. (44)FPGA条件编译(选择语句)
  7. Excel 2003 实用技巧 (FROM MSDN)
  8. fgui的ui管理框架_GitHub - zyswx/DCET: Unity3D客户端和.Net Core服务器双端框架,支持FGUI和双端行为树,支持代码全热更(包括FGUI和行为树)...
  9. 不是 SELECTed 表达式
  10. 基于Simulink使用激光雷达数据跟踪车辆仿真(附源码)
  11. BootCDN和npm
  12. FOC——18.单片机CPU内核框图
  13. square在matlab是什么意思,square是什么意思
  14. 软件测试课程设计——智云云盘
  15. android ota功能,支持 OTA 更新  |  Android 开源项目  |  Android Open Source Project
  16. 计算机用户管理权限有哪些,Windows系统管理员账户和普通账户的详细权限区别有哪些?...
  17. 信息泄露,那些央视没报的“内鬼
  18. aws的eks平滑删除work节点实现降配
  19. DVWA V1.9:Reflected Cross Site Scripting(存储型XSS)
  20. covariate shift和batch normalization问题

热门文章

  1. 正则表达式调用“或”变量
  2. 耗时 2 年,用 8.5 万块乐高积木最牛复刻 Apple Park
  3. Android ImageLoader(Android-Universal-Image-Loader)【1】概述及使用简单介绍
  4. node 常见的一些系统问题
  5. POJ 1118 求平面上最多x点共线
  6. 创建交互式shell脚本对话框
  7. 【转】ubuntu UltraEdit 反复试用的办法
  8. 在 iOS 应用中实现飞行模式提醒
  9. Spring Countries在Apusic上部署
  10. 开源ImageFilter库v0.4:新增26种图片效果