前言

CAShapeLayer继承自CALayer,因此,可使用CALayer的所有属性。但是,CAShapeLayer需要和贝塞尔曲线配合使用才有意义。

关于UIBezierPath,请阅读文章:iOS UIBezierPth精讲

基本知识

看看官方说明:

 
1
2
3
4
5
6
7
8
9
 
/* The shape layer draws a cubic Bezier spline in its coordinate space.
*
* The spline is described using a CGPath object and may have both fill
* and stroke components (in which case the stroke is composited over
* the fill). The shape as a whole is composited between the layer's
* contents and its first sublayer.
*/
 

上面只是部分说明内容,由于较长,只放一部分出来。这里是说CAShapeLayer是在其坐标系统内绘制贝塞尔曲线的。因此,使用CAShapeLayer需要与UIBezierPath一起使用。

它有一个path属性,而UIBezierPath就是对CGPathRef类型的封装,因此这两者配合起来使用才可以的哦!

 
1
2
3
 
@property(nullable) CGPathRef path;
 

CAShapeLayer和drawRect的比较

  • drawRect:属于CoreGraphics框架,占用CPU,性能消耗大,不建议重写
  • CAShapeLayer:属于CoreAnimation框架,通过GPU来渲染图形,节省性能。动画渲染直接提交给手机GPU,不消耗内存

这两者各有各的用途,而不是说有了CAShapeLayer就不需要drawRect

温馨提示:drawRect只是一个方法而已,是UIView的方法,重写此方法可以完成我们的绘制图形功能。

CAShapeLayer与UIBezierPath的关系

CAShapeLayerUIBezierPath的关系:

  1. CAShapeLayershape代表形状的意思,所以需要形状才能生效
  2. 贝塞尔曲线可以创建基于矢量的路径,而UIBezierPath类是对CGPathRef的封装
  3. 贝塞尔曲线给CAShapeLayer提供路径,CAShapeLayer在提供的路径中进行渲染。路径会闭环,所以绘制出了Shape
  4. 用于CAShapeLayer的贝塞尔曲线作为path,其path是一个首尾相接的闭环的曲线,即使该贝塞尔曲线不是一个闭环的曲线

CAShapeLayer与UIBezierPath画圆

效果图如下:

 
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
 
- (CAShapeLayer *)drawCircle {
  CAShapeLayer *circleLayer = [CAShapeLayer layer];
  // 指定frame,只是为了设置宽度和高度
  circleLayer.frame = CGRectMake(0, 0, 200, 200);
  // 设置居中显示
  circleLayer.position = self.view.center;
  // 设置填充颜色
  circleLayer.fillColor = [UIColor clearColor].CGColor;
  // 设置线宽
  circleLayer.lineWidth = 2.0;
  // 设置线的颜色
  circleLayer.strokeColor = [UIColor redColor].CGColor;
  
  // 使用UIBezierPath创建路径
  CGRect frame = CGRectMake(0, 0, 200, 200);
  UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:frame];
  
  // 设置CAShapeLayer与UIBezierPath关联
  circleLayer.path = circlePath.CGPath;
  
  // 将CAShaperLayer放到某个层上显示
  [self.view.layer addSublayer:circleLayer];
  
  return circleLayer;
}
 

注意,我们这里不是放在-drawRect:方法中调用的。我们直接将这个CAShaperLayer放到了self.view.layer上,直接呈现出来。

我们创建一个CAShapeLayer,然后配置相关属性,然后再通过UIBezierPath的类方法创建一个内切圆路径,然后将路径指定给CAShapeLayer.path,这就将两者关联起来了。最后,将这个层放到了self.view.layer上呈现出来。

CAShapeLayer与UIBezierPath的简单Loading效果

效果图类似这样(懒自己做图,就百度了一个):

我们调用了上面这个画圆效果的代码:

 
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
 
- (void)drawHalfCircle {
  self.loadingLayer = [self drawCircle];
  
  // 这个是用于指定画笔的开始与结束点
  self.loadingLayer.strokeStart = 0.0;
  self.loadingLayer.strokeEnd = 0.75;
  
  self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1
                                                target:self
                                              selector:@selector(updateCircle)
                                              userInfo:nil
                                               repeats:YES];
}
 
- (void)updateCircle {
  if (self.loadingLayer.strokeEnd > 1 && self.loadingLayer.strokeStart < 1) {
    self.loadingLayer.strokeStart += 0.1;
  } else if (self.loadingLayer.strokeStart == 0) {
    self.loadingLayer.strokeEnd += 0.1;
  }
  
  if (self.loadingLayer.strokeEnd == 0) {
    self.loadingLayer.strokeStart = 0;
  }
  
  if (self.loadingLayer.strokeStart >= 1 && self.loadingLayer.strokeEnd >= 1) {
    self.loadingLayer.strokeStart = 0;
    [self.timer invalidate];
    self.timer = nil;
  }
}
 

我们要实现这个效果,是通过strokeStarstrokeEnd这两个属性来完成的,看看官方说明:

 
1
2
3
4
5
6
7
8
9
10
11
 
/* These values define the subregion of the path used to draw the
* stroked outline. The values must be in the range [0,1] with zero
* representing the start of the path and one the end. Values in
* between zero and one are interpolated linearly along the path
* length. strokeStart defaults to zero and strokeEnd to one. Both are
* animatable. */
 
@property CGFloat strokeStart;
@property CGFloat strokeEnd;
 

这里说明了这两个值的范围是[0,1],当strokeStart的值为0慢慢变成1时,我们看到路径是慢慢消失的。这里实现的效果并不好,因为不能一起循环着。不过,在这里学习的目的已经达到了,后面学习动画效果时,才专门学习它。

iOS CAShapeLayer精讲的更多相关文章

  1. iOS开发——语法篇OC篇&高级语法精讲二

    Objective高级语法精讲二 Objective-C是基于C语言加入了面向对象特性和消息转发机制的动态语言,这意味着它不仅需要一个编译器,还需要Runtime系统来动态创建类和对象,进行消息发送和 ...

  2. iOS开发——语法篇OC篇&高级语法精讲

    高级语法精讲 一.NSSet.NSMutableSet集合的介绍 1)NSSet.NSMutableSet集合,元素是无序的,不能有重复的值. 2)用实例方法创建一个不可变集合对象 例如: //宏定义 ...

  3. WKWebView API精讲(OC)

    WKWebView API精讲(OC) 前言 鉴于LL同志对笔者说:“能不能写个OC版本的WKWebView的使用教程?”,还积极打赏了30RMB,笔者又怎么好意思拒绝呢,于是才有了下文. 所有看到本 ...

  4. iOS-UI控件精讲之UIView

    道虽迩,不行不至:事虽小,不为不成. 相关阅读 1.iOS-UI控件精讲之UIView(本文) 2.iOS-UI控件精讲之UILabel ...待续 UIView是所有UI控件的基类,在布局的时候通常 ...

  5. 微软BI SSIS 2012 ETL 控件与案例精讲课程学习方式与面试准备详解

    开篇介绍 微软BI SSIS 2012 ETL 控件与案例精讲 (http://www.hellobi.com/course/21) 课程从2014年9月开始准备,到2014年12月在 天善BI学院  ...

  6. 第三百五十节,Python分布式爬虫打造搜索引擎Scrapy精讲—selenium模块是一个python操作浏览器软件的一个模块,可以实现js动态网页请求

    第三百五十节,Python分布式爬虫打造搜索引擎Scrapy精讲—selenium模块是一个python操作浏览器软件的一个模块,可以实现js动态网页请求 selenium模块 selenium模块为 ...

  7. 深入Java核心 Java内存分配原理精讲

    深入Java核心 Java内存分配原理精讲 栈.堆.常量池虽同属Java内存分配时操作的区域,但其适用范围和功用却大不相同.本文将深入Java核心,详细讲解Java内存分配方面的知识. Java内存分 ...

  8. 《VC++ 6简明教程》即VC++ 6.0入门精讲 学习进度及笔记

    VC++6.0入门→精讲 2013.06.09,目前,每一章的“自测题”和“小结”三个板块还没有看(备注:第一章的“实验”已经看完). 2013.06.16 第三章的“实验”.“自测题”.“小结”和“ ...

  9. 【C++自我精讲】基础系列二 const

    [C++自我精讲]基础系列二 const 0 前言 分三部分:const用法.const和#define比较.const作用. 1 const用法 const常量:const可以用来定义常量,不可改变 ...

随机推荐

  1. 198. House Robber

    题目: You are a professional robber planning to rob houses along a street. Each house has a certain am ...

  2. node.js模块之util模块

    util提供了各种使用的工具.require('util') to access them. Util.format(format,[..]) Returns a formatted string u ...

  3. 搜索插件:ack.vim

    ack.vim是Perl脚本ack的前端,对于Vim,也是grepprg和quickfix的简单封装,非常适合搜索 github地址为 https://github.com/mileszs/ack.v ...

  4. Error Code: 1175

    用mysql workbench 更新一个表的时候报如下异常: Error Code: 1175. To disable safe mode, toggle the option in Prefere ...

  5. C#.Net 如何动态加载与卸载程序集(.dll或者.exe)2----通过应用程序域AppDomain加载和卸载程序集之后,如何再返回原来的主程序域

    实现目的:动态加载dll,执行完毕之后可以随时卸载掉,并可以替换这些dll,以在运行中更新dll中的类. 其实就是通过应用程序域AppDomain加载和卸载程序集. 在这方面微软有篇文章http:// ...

  6. git stash

      https://git-scm.com/docs/git-stash   NAME git-stash - Stash the changes in a dirty working directo ...

  7. Java面试题-并发框架

    1. SynchronizedMap和ConcurrentHashMap有什么区别?  答:java5中新增了ConcurrentMap接口和它的一个实现类ConcurrentHashMap.Conc ...

  8. poj3694Network(tarjan+lca)

    http://poj.org/problem?id=3694 用tarjan算出桥,用lca算出公共祖先 把路上的边更新掉 原来的桥变为不是桥 看一解题报告感觉有一部分是不用加的 不知道是不是数据水 ...

  9. awesome awesomeness

    Awesome Awesomeness A curated list of amazingly awesome awesomeness.Also available on: Awesome-Aweso ...

  10. bzoj2595

    一开始看是插头dp,后来发现还有一个叫斯坦纳树的东西 什么叫斯坦纳树,就是使给定点连通开销和最小的树(可以包含多余的点) 到这张平面图上,我们不难想到用dp来解决,设f[x,y,S]表示连通集合为S, ...