CAShapeLayer+UIBezierPath,你能画什么的图形

1,579 阅读4分钟

今天UI设计图里面有个三角形的图形,还专门帮我切好了,想一下我要下载图片,再拖到工程,再写个UIImageView控件,我还是选择画两条线好了,通常情况我都是很喜欢直接UI切图用,毕竟快啊

1.CAShapeLayer

CAShapeLayer,它的父类是CALayer,它的好处是有一个关键属性Path,有了Path,它就可以和UIBezierPath关联起来了。

CAShapeLayer属于CoreAnimation框架,通过GPU来渲染图形,节省性能。动画渲染直接提交给手机GPU,不消耗内存。

所以我们很多时候,都不用DrawRect,这个也可以实现画图形。DrawRect占用CPU,消耗性能较大。

下面我们就列一下CAShapeLayer常用的属性。

  • path:图像形状的路径,UIBezierPath画好,就赋值给它。

  • fillColor:图像填充颜色,类似于backgroundColor。

  • strokeColor:边线的颜色,类似于borderColor。

  • strokeStart,strokeEnd:边线的起点和终点,一般我们可以用CABasicAnimation来赋予动画。

  • lineWidth:边线的宽度,类似于borderWidth。

  • lineCap:边线终点样式,Round为圆形端点,Square为方形端点。

  • lineJoin:边线拐点样式,Round圆形拐点

2.UIBezierPath

UIBezierPath是负责画各种简单的图形,CAShapeLayer是负责把画的路径渲染出来。

我们先列一下常用的方法。

  • moveToPoint:一开始画线调用的方法。也可以说是起点位置。

  • addLineToPoint:添加一个直线。

  • addArcWithCenter:添加一个圆弧

  • addQuadCurveToPoint:添加一个曲线

  • addCurveToPoint: 添加一个二段曲线

有一些在初始化的时候也能画图形。

  • bezierPathWithOvalInRect:画一个椭圆

  • bezierPathWithRect:画一个矩形

  • bezierPathWithRoundedRect:画一个圆角矩形

  • bezierPathWithRoundedRect:byRoundingCorners:某个圆角的矩形

  • bezierPathWithArcCenter:画一个圆弧

  • bezierPathWithCGPath:添加一个路径

有了上面这些,我们就可以画线,画矩形,画椭圆等等。然后就是各种组合了。下面我们就来演示一下UIBezierPath配合CAShapeLayer能画出来什么东西。

2.1.画三角形

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 200, self.view.frame.size.width, 400)];
    view.backgroundColor = [UIColor blueColor];
    [self.view addSubview:view];
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(200, 100)];
    [path addLineToPoint:CGPointMake(300, 200)];
    [path addLineToPoint:CGPointMake(100, 200)];
    [path closePath];
    
    // 设置路径画布
    CAShapeLayer *lineLayer = [CAShapeLayer layer];
    lineLayer.lineWidth = 3.0;
    lineLayer.strokeColor = [UIColor redColor].CGColor;
    lineLayer.path = path.CGPath;
    lineLayer.fillColor = [UIColor yellowColor].CGColor;
    [view.layer addSublayer:lineLayer];


2.2.画扇形

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 200, self.view.frame.size.width, 400)];
    view.backgroundColor = [UIColor blueColor];
    [self.view addSubview:view];
    
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 200) radius:150 startAngle:1.25 * M_PI endAngle:1.75 * M_PI clockwise:YES];
    [path addLineToPoint:CGPointMake(200, 200)];
    [path closePath];
    
    // 设置路径画布
    CAShapeLayer *lineLayer = [CAShapeLayer layer];
    lineLayer.lineWidth = 3.0;
    lineLayer.strokeColor = [UIColor redColor].CGColor;
    lineLayer.path = path.CGPath;
    lineLayer.fillColor = [UIColor yellowColor].CGColor;  
    lineLayer.lineCap = kCALineCapRound;
    lineLayer.lineJoin = kCALineJoinRound; 
    [view.layer addSublayer:lineLayer];


对于这个方法。

UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 200) radius:150 startAngle:1.25 * M_PI endAngle:1.75 * M_PI clockwise:YES];

我们还是简单说一下

嗯,就是一个图,第一个CGPointMake(200, 200)是指中心点位置。Radius就是圆角大小。

startAngle是指圆的开始角度,endAngle是指结束角度,clockwise为YES就是顺时针。

2.3.画二次曲线

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 200, self.view.frame.size.width, 400)];
    view.backgroundColor = [UIColor blueColor];
    [self.view addSubview:view];
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(50, 225)];
    [path addQuadCurveToPoint:CGPointMake(150, 200) controlPoint:CGPointMake(75, 100)];
    [path addQuadCurveToPoint:CGPointMake(250, 175) controlPoint:CGPointMake(225, 300)];
    [path closePath];
    
    // 设置路径画布
    CAShapeLayer *lineLayer = [CAShapeLayer layer];
    lineLayer.lineWidth = 3.0;
    lineLayer.strokeColor = [UIColor redColor].CGColor; 
    lineLayer.path = path.CGPath;
    lineLayer.fillColor = [UIColor yellowColor].CGColor;   
    lineLayer.lineCap = kCALineCapRound;
    lineLayer.lineJoin = kCALineJoinRound; 
    [view.layer addSublayer:lineLayer];


图形是丑了点,这里主要是要说一下控制点。

控制点的位置,会改变圆弧的形状,类似上图。

2.4.画矩形某圆角

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 200, self.view.frame.size.width, 400)];
    view.backgroundColor = [UIColor blueColor];
    [self.view addSubview:view];
    
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(100, 100, 200, 150) byRoundingCorners:UIRectCornerTopRight cornerRadii:CGSizeMake(20, 20)];
    
    // 设置路径画布
    CAShapeLayer *lineLayer = [CAShapeLayer layer];
    lineLayer.lineWidth = 3.0;
    lineLayer.strokeColor = [UIColor redColor].CGColor; 
    lineLayer.path = path.CGPath;
    lineLayer.fillColor = [UIColor yellowColor].CGColor;   
    lineLayer.lineCap = kCALineCapRound;
    lineLayer.lineJoin = kCALineJoinRound; 
    [view.layer addSublayer:lineLayer];


2.5.组合图形

最后一个,来一下以前项目曾经画过的图案。

    CGSize size = self.view.frame.size;
    CGFloat height = 80;
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, size.height - height -34, size.width, height)];
    [self.view addSubview:view];
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(0, 30)];
    [path addLineToPoint:CGPointMake(0, height)];
    [path addLineToPoint:CGPointMake(size.width, height)];
    [path addLineToPoint:CGPointMake(size.width, 30)];
    [path addLineToPoint:CGPointMake(size.width/2 + 60, 30)];
    [path addArcWithCenter:CGPointMake(size.width/2, 30) radius:30 startAngle:2*M_PI endAngle:1*M_PI clockwise:NO];
    [path closePath];
    
    // 设置路径画布
    CAShapeLayer *lineLayer = [CAShapeLayer layer];
    lineLayer.position = CGPointMake(0, 0);
    lineLayer.lineWidth = 3.0;
    lineLayer.strokeColor = [UIColor redColor].CGColor; 
    lineLayer.path = path.CGPath;
    lineLayer.fillColor = [UIColor yellowColor].CGColor;   
    lineLayer.lineCap = kCALineCapRound;
    lineLayer.lineJoin = kCALineJoinRound; 
    [view.layer addSublayer:lineLayer];


3.总结

从上面的各种例子,我们心中大概就知道可以利用CAShapeLayer+UIBezierPath,画出我们想要的图形了。

到了这么基本就差不多了,最后我抛出一点CAShapeLayer还能做什么呢,就是渲染路径吗?细心的我们还看到CASahpeLayer的一个方法。

- (void)addAnimation:(CAAnimation *)anim forKey:(nullable NSString *)key;

动画。

没错,那下一篇,我们就来玩玩如何进行图形动画啦。

喜欢的朋友,点个赞啊,谢谢各位。