看到这张图,是不是觉得挺萌的,那是如何实现的呢?在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