[TOC]

CAShapeLayer

@available(iOS 3.0, *)
open class CAShapeLayer : CALayer

CAShapeLayer继承自CALayer,因此,可使用CALayer的所有属性。

CAShapeLayer在初始化时也需要给一个frame值,但是,它本身没有形状,它的形状来源于你给定的一个path,然后它去取CGPath值,它与CALayer有着很大的区别

几个要点:

  1. 它依附于一个给定的path,必须给与path,而且,即使path不完整也会自动首尾相接
  2. strokeStart以及strokeEnd代表着在这个path中所占用的百分比

因此,CAShapeLayer需要和贝塞尔曲线配合使用才有意义。它有一个path属性,用来配合UIBezierPath(是对CGPathRef类型封装)。

@property(nullable) CGPathRef path;

与drawRect比较:

  • drawRect:属于CoreGraphics框架,占用CPU,性能消耗大,不建议重写

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

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

API:

@interface CAShapeLayer : CALayer

@property(nullable) CGPathRef path;  //根据路径来确定layer的方位

@property(nullable) CGColorRef fillColor;
@property(copy) NSString *fillRule;

@property(nullable) CGColorRef strokeColor;
@property CGFloat strokeStart; //开始点
@property CGFloat strokeEnd; //结束点

@property CGFloat lineWidth;
@property CGFloat miterLimit;
@property(copy) NSString *lineCap;
@property(copy) NSString *lineJoin;
@property CGFloat lineDashPhase;
@property(nullable, copy) NSArray<NSNumber *> *lineDashPattern;

@end

/* `fillRule' values. */
CA_EXTERN NSString *const kCAFillRuleNonZero;
CA_EXTERN NSString *const kCAFillRuleEvenOdd;

/* `lineJoin' values. */
CA_EXTERN NSString *const kCALineJoinMiter;  //斜接
CA_EXTERN NSString *const kCALineJoinRound;
CA_EXTERN NSString *const kCALineJoinBevel; //成斜角

/* `lineCap' values. */
CA_EXTERN NSString *const kCALineCapButt;  //粗大的一端
CA_EXTERN NSString *const kCALineCapRound;
CA_EXTERN NSString *const kCALineCapSquare;

应用

画圆:

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


- (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;
}

Loading效果:

- (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;
  }
}


///
/*
要实现这个效果,是通过strokeStar和strokeEnd这两个属性来完成的:

@property CGFloat strokeStart;
@property CGFloat strokeEnd;

这两个值的范围是[0,1],
当strokeStart的值为0慢慢变成1时,我们看到路径是慢慢消失的。
*/

results matching ""

    No results matching ""