欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-12-19 14:06:40
看到这张图,是不是觉得挺萌的,那是如何实现的呢?在ios中有一个类叫uibezierpath(贝塞尔曲线),这两天研究了一下uibezierpath和cashapela...

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、先画头部。先画一个圆。

//  确定头部所在的圆心
  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、画脸部。画一个比头部小点的圆,与头部圆的底部内切。

 //脸
  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、画眼部

  //左眼
  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、画鼻子、嘴巴、胡须

  //鼻子
  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、画左手部分

 //左手
  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、画身体部分

//围巾
  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、画右手部分

  //右手
  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、给各个部位上颜色

 //上色
  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地址 

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

上一篇:

下一篇: