看到这张图,是不是觉得挺萌的,那是如何实现的呢?在ios中有一个类叫uibezierpath(贝塞尔曲线),这两天研究了一下uibezierpath和cashapelayer,根据别人分享的教程,画了这个萌萌的哆啦a梦。
uibezierpath: uibezierpath是在 uikit 中的一个类,继承于nsobject,可以创建基于矢量的路径.此类是core graphics框架关于path的一个oc封装。使用此类可以定义常见的圆形、多边形等形状 。我们使用直线、弧(arc)来创建复杂的曲线形状。每一个直线段或者曲线段的结束的地方是下一个的开始的地方。每一个连接的直线或者曲线段的集合成为subpath。一个uibezierpath对象定义一个完整的路径包括一个或者多个subpaths。
cashapelayer: 继承于calayer。 每个cashapelayer对象都代表着将要被渲染到屏幕上的一个任意的形状(shape)。具体的形状由其path(类型为cgpathref)属性指定。 普通的calayer是矩形,所以需要frame属性。cashapelayer它本身没有形状,它的形状来源于其属性path 。cashapelayer有不同于calayer的属性,它从calayer继承而来的属性在绘制时是不起作用的。
基本用法:
画圆弧: + (instancetype)bezierpathwitharccenter:(cgpoint)center radius:(cgfloat)radius startangle:(cgfloat)startangle endangle:(cgfloat)endangle clockwise:(bool)clockwise;
- center表示圆心
- radius表示半径
- startangle表示开始角度
- endangle表示结束角度
- clockwise表示是否是顺时针方向
画二元曲线和三元曲线,一般和movetopoint
配合使用。
- 二元曲线:- (void)addquadcurvetopoint:(cgpoint)endpoint controlpoint:(cgpoint)controlpoint
- 三元曲线:- (void)addcurvetopoint:(cgpoint)endpoint controlpoint1:(cgpoint)controlpoint1 controlpoint2:(cgpoint)controlpoint2
其中 endpoint表示:曲线的终点 ;controlpoint表示:画曲线的基准点
知道基本画法后我们就可以画哆啦a梦了。
1、先画头部。先画一个圆。
1
2
3
4
5
6
7
8
9
10
|
// 确定头部所在的圆心 cgfloat headcornerradius=80; cgfloat arccenterx=self.view.frame.size.width/2; cgfloat arccentery= 120+headcornerradius; //画头部 cashapelayer *headlayer=[[cashapelayer alloc] init]; uibezierpath *headpath=[uibezierpath bezierpathwithroundedrect:cgrectmake(self.view.frame.size.width/2-headcornerradius, 120, headcornerradius*2, headcornerradius*2) cornerradius:headcornerradius]; [self setlayer:headlayer path:headpath]; |
2、画脸部。画一个比头部小点的圆,与头部圆的底部内切。
1
2
3
4
|
//脸 cashapelayer *facelayer=[cashapelayer layer]; uibezierpath *facepath=[uibezierpath bezierpathwitharccenter:cgpointmake(self.view.frame.size.width/2, 120+headcornerradius+10) radius:70 startangle:m_pi endangle:3*m_pi clockwise:yes]; [self setlayer:facelayer path:facepath]; |
3、画眼部
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
//左眼 cashapelayer *lefteyelayer = [cashapelayer layer]; uibezierpath *lefteyepath = [uibezierpath bezierpath]; [lefteyepath movetopoint:cgpointmake(arccenterx-30, arccentery-25)]; [lefteyepath addquadcurvetopoint:cgpointmake(arccenterx-15, arccentery-45) controlpoint:cgpointmake(arccenterx-30, arccentery-45)]; [lefteyepath addquadcurvetopoint:cgpointmake(arccenterx, arccentery-25) controlpoint:cgpointmake(arccenterx, arccentery-45)]; [lefteyepath addquadcurvetopoint:cgpointmake(arccenterx-15, arccentery-5) controlpoint:cgpointmake(arccenterx, arccentery-5)]; [lefteyepath addquadcurvetopoint:cgpointmake(arccenterx-30, arccentery-25) controlpoint:cgpointmake(arccenterx-30, arccentery-5)]; [self setlayer:lefteyelayer path:lefteyepath]; //左眼珠 cashapelayer *lefteyeballlayer = [cashapelayer layer]; uibezierpath *lefteyeballpath = [uibezierpath bezierpathwitharccenter:cgpointmake(arccenterx-5, arccentery-30) radius:2.5 startangle:0 endangle:2*m_pi clockwise:yes]; [self setlayer:lefteyeballlayer path:lefteyeballpath ]; //右眼 cashapelayer *righteyelayer = [cashapelayer layer]; uibezierpath *righteyepath = [uibezierpath bezierpath]; [righteyepath movetopoint:cgpointmake(arccenterx, arccentery-25)]; [righteyepath addquadcurvetopoint:cgpointmake(arccenterx+15, arccentery-45) controlpoint:cgpointmake(arccenterx, arccentery-45)]; [righteyepath addquadcurvetopoint:cgpointmake(arccenterx+30, arccentery-25) controlpoint:cgpointmake(arccenterx+30, arccentery-45)]; [righteyepath addquadcurvetopoint:cgpointmake(arccenterx+15, arccentery-5) controlpoint:cgpointmake(arccenterx+30, arccentery-5)]; [righteyepath addquadcurvetopoint:cgpointmake(arccenterx, arccentery-25) controlpoint:cgpointmake(arccenterx, arccentery-5)]; [self setlayer:righteyelayer path:righteyepath ]; //右眼珠 cashapelayer *righteyeballlayer = [cashapelayer layer]; uibezierpath *righteyeballpath = [uibezierpath bezierpathwitharccenter:cgpointmake(arccenterx+5, arccentery-30) radius:2.5 startangle:0 endangle:2*m_pi clockwise:yes]; [self setlayer:righteyeballlayer path:righteyeballpath]; |
4、画鼻子、嘴巴、胡须
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
//鼻子 cashapelayer *noselayer = [cashapelayer layer]; uibezierpath *nosepath = [uibezierpath bezierpathwitharccenter:cgpointmake(arccenterx, arccentery) radius:10 startangle:0 endangle:2*m_pi clockwise:yes]; [self setlayer:noselayer path:nosepath ]; //鼻子光晕 cashapelayer *nosehalolayer = [cashapelayer layer]; uibezierpath *nosehalopath = [uibezierpath bezierpathwitharccenter:cgpointmake(arccenterx-4, arccentery-5) radius:2.5 startangle:0 endangle:2*m_pi clockwise:yes]; [self setlayer:nosehalolayer path:nosehalopath ]; //嘴巴 cashapelayer *mouthlayer = [cashapelayer layer]; uibezierpath *mouthpath = [uibezierpath bezierpath]; [mouthpath movetopoint:cgpointmake(arccenterx-60, arccentery+25)]; [mouthpath addquadcurvetopoint:cgpointmake(arccenterx+60, arccentery+25) controlpoint:cgpointmake(arccenterx, arccentery+90)]; [self setlayer:mouthlayer path:mouthpath]; cashapelayer *mouthlayer1 = [cashapelayer layer]; uibezierpath *mouthpath1 = [uibezierpath bezierpath]; [mouthpath1 movetopoint:cgpointmake(arccenterx, arccentery+10)]; [mouthpath1 addlinetopoint:cgpointmake(arccenterx, arccentery+55)]; [self setlayer:mouthlayer1 path:mouthpath1]; //胡须 [self addbeardfrompoint:cgpointmake(arccenterx-58, arccentery-5) topoint:cgpointmake(arccenterx-15, arccentery+10) ]; [self addbeardfrompoint:cgpointmake(arccenterx-68, arccentery+15) topoint:cgpointmake(arccenterx-15, arccentery+20) ]; [self addbeardfrompoint:cgpointmake(arccenterx-61, arccentery+45) topoint:cgpointmake(arccenterx-15, arccentery+30) ]; [self addbeardfrompoint:cgpointmake(arccenterx+58, arccentery-5) topoint:cgpointmake(arccenterx+15, arccentery+10) ]; [self addbeardfrompoint:cgpointmake(arccenterx+68, arccentery+15) topoint:cgpointmake(arccenterx+15, arccentery+20) ]; [self addbeardfrompoint:cgpointmake(arccenterx+61, arccentery+45) topoint:cgpointmake(arccenterx+15, arccentery+30) ]; |
5、画左手部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//左手 cashapelayer *lefthandlayer = [cashapelayer layer]; uibezierpath *lefthandpath = [uibezierpath bezierpathwitharccenter:cgpointmake(arccenterx-95, arccentery+110) radius:20 startangle:0 endangle:2*m_pi clockwise:yes]; [self setlayer:lefthandlayer path:lefthandpath ]; //左胳膊 cgfloat distancextoarccenter = 80* cos (m_pi_2*4/9); cgfloat distanceytoarccenter = 80* sin (m_pi_2*4/9); cashapelayer *leftarmlayer = [cashapelayer layer]; uibezierpath *leftarmpath = [uibezierpath bezierpath]; [leftarmpath movetopoint:cgpointmake(arccenterx-distancextoarccenter, arccentery+distanceytoarccenter)]; [leftarmpath addlinetopoint:cgpointmake(arccenterx-95, arccentery+90)]; [leftarmpath addquadcurvetopoint:cgpointmake(arccenterx-75, arccentery+110) controlpoint:cgpointmake(arccenterx-92, arccentery+107)]; [leftarmpath addlinetopoint:cgpointmake(arccenterx-distancextoarccenter+1.5, arccentery+95)]; [self setlayer:leftarmlayer path:leftarmpath ]; |
6、画身体部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
//围巾 cashapelayer *mufflerlayer = [cashapelayer layer]; uibezierpath *mufflerpath = [uibezierpath bezierpath]; [mufflerpath movetopoint:cgpointmake(arccenterx-distancextoarccenter, arccentery+distanceytoarccenter)]; [mufflerpath addquadcurvetopoint:cgpointmake(arccenterx+distancextoarccenter, arccentery+distanceytoarccenter) controlpoint:cgpointmake(arccenterx, arccentery+109)]; [mufflerpath addlinetopoint:cgpointmake(arccenterx+distancextoarccenter+2, arccentery+distanceytoarccenter+7)]; [mufflerpath addquadcurvetopoint:cgpointmake(arccenterx-distancextoarccenter-4, arccentery+distanceytoarccenter+5) controlpoint:cgpointmake(arccenterx, arccentery+115)]; [mufflerpath addlinetopoint:cgpointmake(arccenterx-distancextoarccenter, arccentery+distanceytoarccenter)]; [self setlayer:mufflerlayer path:mufflerpath ]; //身体 cashapelayer *bodylayer = [cashapelayer layer]; uibezierpath *bodypath = [uibezierpath bezierpath]; [bodypath movetopoint:cgpointmake(arccenterx-distancextoarccenter, arccentery+distanceytoarccenter+7)]; [bodypath addquadcurvetopoint:cgpointmake(arccenterx-distancextoarccenter+5, arccentery+150) controlpoint:cgpointmake(arccenterx-distancextoarccenter+2, arccentery+140)]; [bodypath addquadcurvetopoint:cgpointmake(arccenterx-distancextoarccenter+3, arccentery+170) controlpoint:cgpointmake(arccenterx-distancextoarccenter, arccentery+160)]; [bodypath addquadcurvetopoint:cgpointmake(arccenterx-8, arccentery+170) controlpoint:cgpointmake(arccenterx-(distancextoarccenter+5)/2, arccentery+175)]; [bodypath addquadcurvetopoint:cgpointmake(arccenterx+8, arccentery+170) controlpoint:cgpointmake(arccenterx, arccentery+155)]; [bodypath addquadcurvetopoint:cgpointmake(arccenterx+distancextoarccenter-3, arccentery+170) controlpoint:cgpointmake(arccenterx+(distancextoarccenter+5)/2, arccentery+175)]; [bodypath addquadcurvetopoint:cgpointmake(arccenterx+distancextoarccenter-5, arccentery+150) controlpoint:cgpointmake(arccenterx+distancextoarccenter-2, arccentery+160)]; [bodypath addquadcurvetopoint:cgpointmake(arccenterx+distancextoarccenter, arccentery+distanceytoarccenter+8) controlpoint:cgpointmake(arccenterx+distancextoarccenter-2, arccentery+140)]; [bodypath addquadcurvetopoint:cgpointmake(arccenterx-distancextoarccenter, arccentery+distanceytoarccenter+7) controlpoint:cgpointmake(arccenterx, arccentery+115)]; [self setlayer:bodylayer path:bodypath ]; //左脚 cashapelayer *leftfootlayer = [cashapelayer layer]; uibezierpath *leftfootpath = [uibezierpath bezierpath]; [leftfootpath movetopoint:cgpointmake(arccenterx-distancextoarccenter+3, arccentery+170)]; [leftfootpath addquadcurvetopoint:cgpointmake(arccenterx-distancextoarccenter+3, arccentery+195) controlpoint:cgpointmake(arccenterx-distancextoarccenter-20, arccentery+185)]; [leftfootpath addquadcurvetopoint:cgpointmake(arccenterx-13, arccentery+195) controlpoint:cgpointmake(arccenterx-(distancextoarccenter+10)/2, arccentery+200)]; [leftfootpath addquadcurvetopoint:cgpointmake(arccenterx-10, arccentery+170) controlpoint:cgpointmake(arccenterx+8, arccentery+187)]; [self setlayer:leftfootlayer path:leftfootpath ]; //右脚 cashapelayer *rightfootlayer = [cashapelayer layer]; uibezierpath *rightfootpath = [uibezierpath bezierpath]; [rightfootpath movetopoint:cgpointmake(arccenterx+10, arccentery+170)]; [rightfootpath addquadcurvetopoint:cgpointmake(arccenterx+15, arccentery+195) controlpoint:cgpointmake(arccenterx-12, arccentery+185)]; [rightfootpath addquadcurvetopoint:cgpointmake(arccenterx+distancextoarccenter-5, arccentery+195) controlpoint:cgpointmake(arccenterx+(distancextoarccenter+20)/2, arccentery+200)]; [rightfootpath addquadcurvetopoint:cgpointmake(arccenterx+distancextoarccenter-3, arccentery+170) controlpoint:cgpointmake(arccenterx+distancextoarccenter+18, arccentery+185)]; [self setlayer:rightfootlayer path:rightfootpath]; //肚子 cashapelayer *bellylayer = [cashapelayer layer]; uibezierpath *bellypath = [uibezierpath bezierpath]; [bellypath movetopoint:cgpointmake(arccenterx-30, arccentery+80)]; [bellypath addcurvetopoint:cgpointmake(arccenterx-30, arccentery+150) controlpoint1:cgpointmake(arccenterx-65, arccentery+95) controlpoint2:cgpointmake(arccenterx-60, arccentery+140)]; [bellypath addquadcurvetopoint:cgpointmake(arccenterx+30, arccentery+150) controlpoint:cgpointmake(arccenterx, arccentery+160)]; [bellypath addcurvetopoint:cgpointmake(arccenterx+30, arccentery+80) controlpoint1:cgpointmake(arccenterx+60, arccentery+140) controlpoint2:cgpointmake(arccenterx+65, arccentery+95)]; [bellypath addquadcurvetopoint:cgpointmake(arccenterx-30, arccentery+80) controlpoint:cgpointmake(arccenterx, arccentery+92)]; [self setlayer:bellylayer path:bellypath ]; //铃铛 cashapelayer *belllayer = [cashapelayer layer]; uibezierpath *bellpath = [uibezierpath bezierpathwitharccenter:cgpointmake(arccenterx, arccentery+97) radius:15 startangle:0 endangle:2*m_pi clockwise:yes]; [self setlayer:belllayer path:bellpath ]; //铃铛上的线 cashapelayer *belllinelayer = [cashapelayer layer]; uibezierpath *belllinepath = [uibezierpath bezierpath]; [belllinepath movetopoint:cgpointmake(arccenterx-( sqrt ( pow (15.0, 2)- pow (5.0, 2))), arccentery+92)]; [belllinepath addlinetopoint:cgpointmake(arccenterx+( sqrt ( pow (15.0, 2)- pow (5.0, 2))), arccentery+92)]; [belllinepath movetopoint:cgpointmake(arccenterx+( sqrt ( pow (15.0, 2)- pow (2.0, 2))), arccentery+95)]; [belllinepath addlinetopoint:cgpointmake(arccenterx-( sqrt ( pow (15.0, 2)- pow (2.0, 2))), arccentery+95)]; [self setlayer:belllinelayer path:belllinepath ]; //铃铛上的小圆点 cashapelayer *bellcirlayer = [cashapelayer layer]; uibezierpath *bellcirpath = [uibezierpath bezierpathwitharccenter:cgpointmake(arccenterx, arccentery+102) radius:2.5 startangle:0 endangle:2*m_pi clockwise:yes]; [bellcirpath movetopoint:cgpointmake(arccenterx, arccentery+104.5)]; [bellcirpath addlinetopoint:cgpointmake(arccenterx, arccentery+112)]; [self setlayer:bellcirlayer path:bellcirpath ]; //口袋 cashapelayer *baglayer = [cashapelayer layer]; uibezierpath *bagpath = [uibezierpath bezierpath]; [bagpath movetopoint:cgpointmake(arccenterx-40, arccentery+112)]; [bagpath addquadcurvetopoint:cgpointmake(arccenterx+40, arccentery+112) controlpoint:cgpointmake(arccenterx, arccentery+120)]; [bagpath addcurvetopoint:cgpointmake(arccenterx-40, arccentery+112) controlpoint1:cgpointmake(arccenterx+28, arccentery+160) controlpoint2:cgpointmake(arccenterx-28, arccentery+160)]; [self setlayer:baglayer path:bagpath ]; |
7、画右手部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
//右手 cashapelayer *righthandlayer = [cashapelayer layer]; uibezierpath *righthandpath = [uibezierpath bezierpathwitharccenter:cgpointmake(arccenterx+85* cos (27/180.0*m_pi), arccentery-85* sin (27/180.0*m_pi)) radius:20 startangle:0 endangle:2*m_pi clockwise:yes]; [self setlayer:righthandlayer path:righthandpath ]; //右胳膊 cashapelayer *rightarmlayer = [cashapelayer layer]; uibezierpath *rightarmpath = [uibezierpath bezierpath]; [rightarmpath movetopoint:cgpointmake(arccenterx+80* cos (13/180.0*m_pi), arccentery-80* sin (13/180.0*m_pi))]; [rightarmpath addquadcurvetopoint:cgpointmake(arccenterx+distancextoarccenter, arccentery+distanceytoarccenter) controlpoint:cgpointmake(arccenterx+80* cos (13/180.0*m_pi)+9, arccentery+20)]; [rightarmpath addlinetopoint:cgpointmake(arccenterx+distancextoarccenter, arccentery+distanceytoarccenter+25)]; [rightarmpath addquadcurvetopoint:cgpointmake(arccenterx+93* cos (15/180.0*m_pi), arccentery-93* sin (15/180.0*m_pi)) controlpoint:cgpointmake(arccenterx+90* cos (13/180.0*m_pi)+15, arccentery+25)]; [rightarmpath addquadcurvetopoint:cgpointmake(arccenterx+80* cos (13/180.0*m_pi), arccentery-80* sin (13/180.0*m_pi)) controlpoint:cgpointmake(arccenterx+80* cos (13/180.0*m_pi)+5, arccentery-93* sin (15/180.0*m_pi)+5)]; [self setlayer:rightarmlayer path:rightarmpath]; uilabel *label = [[uilabel alloc] initwithframe:cgrectmake(self.view.frame.size.width/2+90, 120, 70, 30)]; label.textalignment = nstextalignmentcenter; label.textcolor = [uicolor colorwithred:21/255.0 green:159/255.0 blue:237/255.0 alpha:1]; label.text = @ "hello" ; label.font = [uifont fontwithname:@ "chalkduster" size:20]; [self.view addsubview:label]; cabasicanimation *animation = [cabasicanimation animationwithkeypath:@ "transform.scale" ]; animation.fromvalue = @(0); animation.tovalue = @(1); animation.duration = 0.5f; [label.layer addanimation:animation forkey:nil]; |
8、给各个部位上颜色
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
//上色 facelayer.fillcolor = [uicolor whitecolor].cgcolor; lefteyelayer.fillcolor = [uicolor whitecolor].cgcolor; righteyelayer.fillcolor = [uicolor whitecolor].cgcolor; lefteyeballlayer.fillcolor = [uicolor blackcolor].cgcolor; righteyeballlayer.fillcolor = [uicolor blackcolor].cgcolor; noselayer.fillcolor = [uicolor redcolor].cgcolor; nosehalolayer.fillcolor = [uicolor whitecolor].cgcolor; headlayer.fillcolor = [uicolor colorwithred:21/255.0 green:159/255.0 blue:237/255.0 alpha:1].cgcolor; leftarmlayer.fillcolor = [uicolor colorwithred:21/255.0 green:159/255.0 blue:237/255.0 alpha:1].cgcolor; lefthandlayer.fillcolor = [uicolor whitecolor].cgcolor; mufflerlayer.fillcolor = [uicolor redcolor].cgcolor; bellylayer.fillcolor = [uicolor whitecolor].cgcolor; belllayer.fillcolor = [uicolor yellowcolor].cgcolor; bodylayer.fillcolor = [uicolor colorwithred:21/255.0 green:159/255.0 blue:237/255.0 alpha:1].cgcolor; righthandlayer .fillcolor=[uicolor whitecolor].cgcolor ; rightarmlayer .fillcolor=[uicolor colorwithred:21/255.0 green:159/255.0 blue:237/255.0 alpha:1] .cgcolor; |
这样,一个简单的哆啦a梦就实现了。
文中只展示了重要部分的代码,如果有需要,可以看完整的demo,同时demo里面也展示了uibezierpath和cashapelayer基本的画图方法。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://www.jianshu.com/p/ed44cc1a120e?utm_source=tuicool&utm_medium=referral