iOS贝塞尔曲线画哆啦A梦的代码实例

时间:2022-09-22 17:21:21

iOS贝塞尔曲线画哆啦A梦的代码实例

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

  1. center表示圆心
  2. radius表示半径
  3. startangle表示开始角度
  4. endangle表示结束角度
  5. clockwise表示是否是顺时针方向

画二元曲线和三元曲线,一般和movetopoint配合使用。

  1. 二元曲线:- (void)addquadcurvetopoint:(cgpoint)endpoint controlpoint:(cgpoint)controlpoint
  2. 三元曲线:- (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基本的画图方法。

demo地址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:http://www.jianshu.com/p/ed44cc1a120e?utm_source=tuicool&utm_medium=referral