CALayer的子类之CAShapeLayer

摘要:
CAShapeLayer是在坐标系内绘制贝塞尔曲线的,通过绘制贝塞尔曲线,设置shape(形状)的path(路径),从而绘制各种各样的图形以及不规则图形。通俗点就是UIBezierPath用来指定绘制图形路径,而CAShapeLayer就是根据路径来绘图的。使用CAShapeLayer与贝塞尔曲线可以实现不在view的DrawRect方法中画出一些想要的图形*关于CAShapeLayer和DrawRect的比较DrawRect:DrawRect属于CoreGraphic框架,占用CPU,消耗性能大CAShapeLayer:CAShapeLayer属于CoreAnimation框架,通过GPU来渲染图形,节省性能。

一,CAShapeLayer介绍

* CAShapeLayer继承自CALayer,属于QuartzCore框架,可使用CALayer的所有属性。
CAShapeLayer是在坐标系内绘制贝塞尔曲线的,通过绘制贝塞尔曲线,设置shape(形状)的path(路径),从而绘制各种各样的图形以及不规则图形。因此,使用CAShapeLayer需要与UIBezierPath一起使用。
UIBezierPath类允许你在自定义的 View 中绘制和渲染由直线和曲线组成的路径.。你可以在初始化的时候直接为你的UIBezierPath指定一个几何图形。
通俗点就是UIBezierPath用来指定绘制图形路径,而CAShapeLayer就是根据路径来绘图的。
使用CAShapeLayer与贝塞尔曲线可以实现不在view的DrawRect方法中画出一些想要的图形

*关于CAShapeLayer和DrawRect的比较
DrawRect:DrawRect属于CoreGraphic框架,占用CPU,消耗性能大
CAShapeLayer:CAShapeLayer属于CoreAnimation框架,通过GPU来渲染图形,节省性能。动画渲染直接提交给手机GPU,不消耗内存

二,CAShapeLayer属性介绍

CA_CLASS_AVAILABLE (10.6, 3.0, 9.0, 2.0)

@interface CAShapeLayer : CALayer

1、[CAShapeLayer layer].path

/* The path defining the shape to be rendered. If the path extends
 * outside the layer bounds it will not automatically be clipped to the
 * layer, only if the normal layer masking rules cause that. Upon
 * assignment the path is copied. Defaults to null. Animatable.
 * (Note that although the path property is animatable, no implicit
 * animation will be created when the property is changed.) 
 */
@property(nullable) CGPathRef path;

解释:定义要渲染的形状的路径。 如果路径延伸到图层边界之外,不会自动被图层剪切,则只有在正常的图层遮罩规则才会实现自动剪切。 分配后,路径被复制。 缺省为nil,可动画。 (请注意,虽然path属性是可动画的,但是当属性改变时,不会创建隐式动画。)
示例代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self initUI];
}
-(void)initUI{
    UIBezierPath * path = [UIBezierPath bezierPath];
    [path addArcWithCenter:CGPointMake(200.0, 300.0) radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
    self.shaperLayer = [CAShapeLayer layer];
    self.shaperLayer.path =path.CGPath;
    self.shaperLayer.strokeColor =[UIColor blueColor].CGColor;
    self.shaperLayer.fillColor = [UIColor redColor].CGColor;
    self.shaperLayer.lineWidth = 2;
    self.shaperLayer.frame     = self.view.bounds;
    [self.view.layer addSublayer:self.shaperLayer];
    [self drawLineAnimation:self.shaperLayer];
}
- (void)drawLineAnimation:(CALayer*)layer{
    CABasicAnimation * bas =[CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    bas.duration = 3;
    bas.fromValue =[NSNumber numberWithInteger:0];
    bas.toValue   =[NSNumber numberWithInteger:1];
    [layer addAnimation:bas forKey:@"key"];
}

演示:
CALayer的子类之CAShapeLayer第1张

2、[CAShapeLayer layer].fillColor

/* The color to fill the path, or nil for no fill. Defaults to opaque
 * black. Animatable. */
@property(nullable) CGColorRef fillColor;

解释:官方解释是填充路径的颜色,或无填充时为nil。默认颜色为不透明的黑色,可动画。
示例代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self initUI];
}
-(void)initUI{
    UIBezierPath * path = [UIBezierPath bezierPath];
    [path addArcWithCenter:CGPointMake(200.0, 300.0) radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
    self.shaperLayer = [CAShapeLayer layer];
    self.shaperLayer.path =path.CGPath;
    self.shaperLayer.strokeColor =[UIColor blueColor].CGColor;
    self.shaperLayer.fillColor = [UIColor redColor].CGColor;
    self.shaperLayer.lineWidth = 2;
    self.shaperLayer.frame     = self.view.bounds;
    [self.view.layer addSublayer:self.shaperLayer];
    [self drawLineAnimation:self.shaperLayer];
}
- (void)drawLineAnimation:(CALayer*)layer{
    CABasicAnimation * bas =[CABasicAnimation animationWithKeyPath:@"fillColor"];
    bas.duration = 3;
    bas.fromValue =(__bridge id)[UIColor redColor].CGColor;
    bas.toValue   =(__bridge id)[UIColor blueColor].CGColor;
    [layer addAnimation:bas forKey:@"key"];
}

演示:

CALayer的子类之CAShapeLayer第2张

3、[CAShapeLayer layer].fillRule

/* The fill rule used when filling the path. Options are `non-zero' and
 * `even-odd'. Defaults to `non-zero'. */
@property(copy) NSString *fillRule;

解释:官方解释是当在填充颜色的时候则就需要这种填充规则,值有两种,非零和奇偶数,但默认是非零值。

属性用于指定使用哪一种算法去判断画布上的某区域是否属于该图形“内部” (内部区域将被填充)。对一个简单的无交叉的路径,哪块区域是“内部” 是很直观清除的。但是,对一个复杂的路径,比如自相交或者一个子路径包围另一个子路径,“内部”的理解就不那么明确了。

kCAFillRuleNonZero

字面意思是“非零”。按该规则,要判断一个点是否在图形内,从该点作任意方向的一条射线,然后检测射线与图形路径的交点情况。从0开始计数,路径从左向右穿过射线则计数加1,从右向左穿过射线则计数减1。得出计数结果后,如果结果是0,则认为点在图形外部,否则认为在内部。下图演示了kCAFillRuleNonZero规则:
CALayer的子类之CAShapeLayer第3张

kCAFillRuleEvenOdd

字面意思是“奇偶”。按该规则,要判断一个点是否在图形内,从该点作任意方向的一条射线,然后检测射线与图形路径的交点的数量。如果结果是奇数则认为点在内部,是偶数则认为点在外部。下图演示了kCAFillRuleEvenOdd 规则:
CALayer的子类之CAShapeLayer第4张

4、[CAShapeLayer layer].strokeColor

/* The color to fill the path's stroked outline, or nil for no stroking.
 * Defaults to nil. Animatable. 
 */
@property(nullable) CGColorRef strokeColor;

解释:这个属性用于设置描边的颜色,如果不需要描边就传nil,默认就是nil,该属性还是可动画的。

代码示例:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self initUI];
}
-(void)initUI{
    UIBezierPath * path = [UIBezierPath bezierPath];
    [path addArcWithCenter:CGPointMake(200.0, 300.0) radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
    self.shaperLayer = [CAShapeLayer layer];
    self.shaperLayer.path =path.CGPath;
    self.shaperLayer.strokeColor =[UIColor blueColor].CGColor;
    self.shaperLayer.fillColor = [UIColor redColor].CGColor;
    self.shaperLayer.lineWidth = 2;
    self.shaperLayer.frame     = self.view.bounds;
    [self.view.layer addSublayer:self.shaperLayer];
}

演示:
CALayer的子类之CAShapeLayer第5张


5、[CAShapeLayer layer].strokeStart 与 [CAShapeLayer layer].strokeEnd

/* 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]的范围内,其中0表示路径的开始,1表示结束。 介于0和1之间的值沿路径长度线性插值。strokeStart默认为零,strokeEnd默认为1。 两者都是可以动画的。
代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self initUI];
}
-(void)initUI{
    UIBezierPath * path = [UIBezierPath bezierPath];
    [path addArcWithCenter:CGPointMake(200.0, 300.0) radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
    self.shaperLayer = [CAShapeLayer layer];
    self.shaperLayer.path =path.CGPath;
    self.shaperLayer.strokeColor =[UIColor blueColor].CGColor;
    self.shaperLayer.fillColor = [UIColor redColor].CGColor;
    self.shaperLayer.fillRule  = kCAFillRuleEvenOdd;
    self.shaperLayer.lineWidth = 2;
    self.shaperLayer.strokeStart = 0.1;
    self.shaperLayer.frame     = self.view.bounds;
    [self.view.layer addSublayer:self.shaperLayer];
    [self drawLineAnimation:self.shaperLayer];
}
- (void)drawLineAnimation:(CALayer*)layer{
    CABasicAnimation * bas =[CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    bas.duration = 3;
    bas.fromValue =@0.1;
    bas.toValue   =@0.9;
    [layer addAnimation:bas forKey:@"key"];
}

演示:
CALayer的子类之CAShapeLayer第6张


6、[CAShapeLayer layer].lineWidth 和[CAShapeLayer layer].miterLimit

/* The line width used when stroking the path. Defaults to one.
 * Animatable. 
 */
@property CGFloat lineWidth;
/* The miter limit used when stroking the path. Defaults to ten.
 * Animatable. 
 */ 
@property CGFloat miterLimit;

解释:官方解释是lineWidth为线的宽度,默认为1;miterLimit为最大斜接长度。斜接长度指的是在两条线交汇处和外交之间的距离。只有lineJoin属性为kCALineJoinMiter时miterLimit才有效。边角的角度越小,斜接长度就会越大。为了避免斜接长度过长,我们可以使用miterLimit属性。如果斜接长度超过miterLimit的值,边角会以lineJoin的“bevel”即kCALineJoinBevel类型来显示。

代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self initUI];
}
-(void)initUI{
    UIBezierPath * path = [UIBezierPath bezierPath];
    [path addArcWithCenter:CGPointMake(200.0, 300.0) radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
    self.shaperLayer = [CAShapeLayer layer];
    self.shaperLayer.path =path.CGPath;
    self.shaperLayer.strokeColor =[UIColor blueColor].CGColor;
    self.shaperLayer.fillColor = [UIColor redColor].CGColor;
    self.shaperLayer.fillRule  = kCAFillRuleEvenOdd;
    self.shaperLayer.lineWidth = 2;
    self.shaperLayer.strokeStart = 0.1;
    self.shaperLayer.frame     = self.view.bounds;
    [self.view.layer addSublayer:self.shaperLayer];
    [self drawLineAnimation:self.shaperLayer];
}
- (void)drawLineAnimation:(CALayer*)layer{
    CABasicAnimation * bas =[CABasicAnimation animationWithKeyPath:@"lineWidth"];
    bas.duration = 3;
    bas.fromValue =@3;
    bas.toValue   =@10;
    [layer addAnimation:bas forKey:@"key"];
}

演示:
CALayer的子类之CAShapeLayer第7张


7、[CAShapeLayer layer].lineCap 与[CAShapeLayer layer].lineJoin

/* The cap style used when stroking the path. Options are `butt', `round'
 * and `square'. Defaults to `butt'. 
 */ 
@property(copy) NSString *lineCap;
/* The join style used when stroking the path. Options are `miter', `round'
 * and `bevel'. Defaults to `miter'. 
 */
@property(copy) NSString *lineJoin;

解释:

lineCap为线端点类型,值有三个类型,分别为kCALineCapButt 、kCALineCapRound 、kCALineCapSquare,默认值为Butt;
CALayer的子类之CAShapeLayer第8张
lineJoin为线连接类型,其值也有三个类型,分别为kCALineJoinMiter、kCALineJoinRound、kCALineJoinBevel,默认值是Miter。
CALayer的子类之CAShapeLayer第9张

8、[CAShapeLayer layer].lineDashPhase 与[CAShapeLayer layer].lineDashPattern

/* The phase of the dashing pattern applied when creating the stroke.
 * Defaults to zero. Animatable. 
 */ 
@property CGFloat lineDashPhase;
/* The dash pattern (an array of NSNumbers) applied when creating the
 * stroked version of the path. Defaults to nil. 
 */
@property(nullable, copy) NSArray<NSNumber *> *lineDashPattern;
官方解释是lineDashPhase为线型模版的起始位置;lineDashPattern为线性模版,这是一个NSNumber的数组,索引从1开始记,奇数位数值表示实线长度,偶数位数值表示空白长度。
lineDashPhase:
设置边线的样式,默认为实线,该数组为一个NSNumber数组,数组中的数值依次表示虚线中单个线的长度,和空白的长度,如:数组@[2,2,3,4] 表示 有长度为2的线,长度为2的空白,长度为3的线,长度为4的空白,不断循环后组成的虚线。

CALayer的子类之CAShapeLayer第10张
lineDashPattern
:
边线样式的起始位置,即,如果lineDashPattern设置为@[@2, @2, @3, @4],lineDashPhase即为第一个长度为2的线的起始位置,默认值为0,可动画
注:fillColor与strokeColor都是在有UIBezierPath参数配置的情况下才能发生作用
代码:
- (void)viewDidLoad {
    [super viewDidLoad];
    [self initUI];
}
-(void)initUI{
    UIBezierPath * path = [UIBezierPath bezierPath];
    [path addArcWithCenter:CGPointMake(200.0, 300.0) radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
    self.shaperLayer = [CAShapeLayer layer];
    self.shaperLayer.path =path.CGPath;
    self.shaperLayer.strokeColor =[UIColor blueColor].CGColor;
    self.shaperLayer.fillColor = [UIColor redColor].CGColor;
    self.shaperLayer.fillRule  = kCAFillRuleEvenOdd;
    self.shaperLayer.lineWidth = 2;
    self.shaperLayer.frame     = self.view.bounds;
    self.shaperLayer.lineDashPattern = @[@2, @3, @4, @5];
    self.shaperLayer.lineDashPhase   = 1;
    [self.view.layer addSublayer:self.shaperLayer];
}

演示:
CALayer的子类之CAShapeLayer第11张

免责声明:文章转载自《CALayer的子类之CAShapeLayer》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇男神鹏:实现在自己的本地服务器设置域名操作!倒计时睡眠法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Unity3D使用碰撞体做触发器实现简单的自己主动开门

 在游戏制作中触发器的使用很的方便也很有用。 这一张我们简介一下怎样使用一个简单的触发器来实现自己主动开门关门的效果。 首先确保你已经对门进行了动画的设置。 详细流程例如以下。 选择Window->Animation打开动画窗体,选中须要加入动画的门之后点击红色button创建新动画。 选中一个须要加入动画的要素之后(比方Postion...

你知道几种前端动画的实现方式?

随着互联网的持续发展,H5 页面作为与用户直接交互的表现层越来越复杂,呈现的形式也越来越丰富,从而也要求 H5 页面具有更多的花样性及动画效果。那前端实现动画效果的方式有哪些呢,大致有如下几种: 一、GIF图片 GIF图就直接贴上图片就好了,使用非常简单,但GIF图有时出现问题是没办法控制的,比如常见的GIF图的闪烁现象。 二、序列帧 序列帧其实本质是GI...

CSS动画总结效果

   CSS3添加了几个动画效果的属性,通过设置这些属性,可以做出一些简单的动画效果而不需要再去借助JavaScript。CSS3动画的属性主要分为三类:transform、transition以及animation。   transform rotate 设置元素顺时针旋转的角度,用法是: transform: rotate(x); 参数x必须是以...

collection动画

Collection View 动画 吴迪 12 May 2014 分享文章 UICollectionView 和相关类的设置非常灵活和强大。但是灵活性一旦增强,某种程度上也增加了其复杂性: UICollectionView 比老式的 UITableView 更有深度,适用性也更强。 Collection View 深入太多了,事实上,Ole...

css动画延迟好像有点怪

项目中需要使用到动画animate.css,在自定义的时候发现设置animation-delay 和 animation-duration 的总时间不对会导致 动画缺失。比如 bounceInLeft 动画 是从左边出现然后 抖动一下 ,当初始animation-delay为0,animation-duration为1s,动画完整,但是如果设置,anima...

H5动画开发快车道

前言 以往做一些H5的运营项目,都是动画设计师使用Animate cc(原来的Flash)先设计好动画原型,然后交给我们UI开发来实现。做过动画开发的童鞋都知道动画开发都是比较耗费时间精力的,而且还要高质量的还原动画设计师设计好的动画,来回沟通成本也非常高。 那有没有一种高效的方法来改善这种流程,提高开发效率的同时还能完成高品质的动画呢? 经过一段时间的摸...