一 CAShapeLayer 简介
1,CAShapeLayer继承至CALayer,可以使用CALayer的所有属性
2,CAShapeLayer需要与贝塞尔曲线配合使用才有意义;单独使用毫无意义
3,使用CAShapeLayer与贝塞尔可以实现不在view的drawRect方法中画出一些想要的图形;
4,CAShapeLayer属于Core Animation框架,其动画渲染直接提交到手机的GPU当中,相较于view的drawRect方法使用CPU渲染而言,其效率极高,
能大大优化内存使用情况。
drawRect 属于Core Graphics 框架,走CPU,耗性能较大。
5,示例:
@interface SubLayerVC () @property (nonatomic, strong) NSTimer *timer; @property (nonatomic, strong) CAShapeLayer *shapeLayer; @end @implementation SubLayerVC - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; // 创建shapeLayer _shapeLayer = [CAShapeLayer layer]; _shapeLayer.frame = (CGRect){CGPointMake(0, 0), CGSizeMake(200, 200)}; _shapeLayer.position = self.view.center; _shapeLayer.path = [self getStar1BezierPath].CGPath; _shapeLayer.fillColor = [UIColor clearColor].CGColor; _shapeLayer.strokeColor = [UIColor redColor].CGColor; _shapeLayer.lineWidth = 2.f; [self.view.layer addSublayer:_shapeLayer]; // 创建定时器 _timer = [NSTimer scheduledTimerWithTimeInterval:1.f target:self selector:@selector(pathAnimation) userInfo:nil repeats:YES]; } /** * 执行path的动画 */ - (void)pathAnimation { static int i = 0; if (i++ % 2 == 0) { CABasicAnimation *circleAnim = [CABasicAnimation animationWithKeyPath:@"path"]; circleAnim.removedOnCompletion = NO; circleAnim.duration = 1; circleAnim.fromValue = (__bridge id)[self getStar1BezierPath].CGPath; circleAnim.toValue = (__bridge id)[self getStar2BezierPath].CGPath; _shapeLayer.path = [self getStar2BezierPath].CGPath; [_shapeLayer addAnimation:circleAnim forKey:@"animateCirclePath"]; } else { CABasicAnimation *circleAnim = [CABasicAnimation animationWithKeyPath:@"path"]; circleAnim.removedOnCompletion = NO; circleAnim.duration = 1; circleAnim.fromValue = (__bridge id)[self getStar2BezierPath].CGPath; circleAnim.toValue = (__bridge id)[self getStar1BezierPath].CGPath; _shapeLayer.path = [self getStar1BezierPath].CGPath; [_shapeLayer addAnimation:circleAnim forKey:@"animateCirclePath"]; } } /** * 贝塞尔曲线1 * * @return 贝塞尔曲线 */ -(UIBezierPath *)getStar1BezierPath { //// Star Drawing UIBezierPath* starPath = [UIBezierPath bezierPath]; [starPath moveToPoint: CGPointMake(22.5, 2.5)]; [starPath addLineToPoint: CGPointMake(28.32, 14.49)]; [starPath addLineToPoint: CGPointMake(41.52, 16.32)]; [starPath addLineToPoint: CGPointMake(31.92, 25.56)]; [starPath addLineToPoint: CGPointMake(34.26, 38.68)]; [starPath addLineToPoint: CGPointMake(22.5, 32.4)]; [starPath addLineToPoint: CGPointMake(10.74, 38.68)]; [starPath addLineToPoint: CGPointMake(13.08, 25.56)]; [starPath addLineToPoint: CGPointMake(3.48, 16.32)]; [starPath addLineToPoint: CGPointMake(16.68, 14.49)]; [starPath closePath]; return starPath; } /** * 贝塞尔曲线2 * * @return 贝塞尔曲线 */ -(UIBezierPath *)getStar2BezierPath { //// Star Drawing UIBezierPath* starPath = [UIBezierPath bezierPath]; [starPath moveToPoint: CGPointMake(22.5, 2.5)]; [starPath addLineToPoint: CGPointMake(32.15, 9.21)]; [starPath addLineToPoint: CGPointMake(41.52, 16.32)]; [starPath addLineToPoint: CGPointMake(38.12, 27.57)]; [starPath addLineToPoint: CGPointMake(34.26, 38.68)]; [starPath addLineToPoint: CGPointMake(22.5, 38.92)]; [starPath addLineToPoint: CGPointMake(10.74, 38.68)]; [starPath addLineToPoint: CGPointMake(6.88, 27.57)]; [starPath addLineToPoint: CGPointMake(3.48, 16.32)]; [starPath addLineToPoint: CGPointMake(12.85, 9.21)]; [starPath closePath]; return starPath; }
二贝赛尔曲线与CAShapeLayer的关系
1,CAShapeLayer,含shape,顾名思义,它需要一个形状才能生效;
2,贝塞尔曲线可以创建基于矢量的路径
3,贝塞尔曲线给CAShapeLayer提供路径,CAShapeLayer在提供的路径中进行渲染,路径会闭环,所以路径绘制出了shape。
4,用于CAShapeLayer的贝塞尔曲线作为path,其path是一个首尾相接的闭环的曲线,即使该贝塞尔曲线不是一个闭环的曲线。
shape.masksToBounds = YES ; //禁止内容显示超出CAShapeLayer的frame值。
贝塞尔曲线的frame值与CAShapeLayer的frame值互不干扰,CAShaperLayer的frame值不能小于贝塞尔曲线的frame值。
三 CAShapeLayer 之 strokeStart与strokeEnd动画
1,将shapeLayer的fillColor设置为透明背景
2,设置线条的宽度(lineWidth)的值
3,设置线条的颜色
4,将strokeStart值设定为0,然后让stokeEnd的值变化触发隐式动画
- (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; // 创建椭圆形贝塞尔曲线 UIBezierPath *oval = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 100, 100)]; // 创建CAShapeLayer _shapeLayer3 = [CAShapeLayer layer]; _shapeLayer3.frame = CGRectMake(0, 0, 100, 100); _shapeLayer3.position = self.view.center; // 修改CAShapeLayer的线条相关值 _shapeLayer3.fillColor = [UIColor clearColor].CGColor; _shapeLayer3.strokeColor = [UIColor redColor].CGColor; _shapeLayer3.lineWidth = 2.f; //0 是最右侧点,0.25是最下方的点,0.5是最左侧的点,0.75是最顶端的点 _shapeLayer3.strokeStart = 0.f; _shapeLayer3.strokeEnd = 0.f; // 建立贝塞尔曲线与CAShapeLayer之间的关联 _shapeLayer3.path = oval.CGPath; // 添加并显示 [self.view.layer addSublayer:_shapeLayer3]; // 创建定时器 _timer = [NSTimer scheduledTimerWithTimeInterval:1.f target:self selector:@selector(animationEventTypeTwo) userInfo:nil repeats:YES]; } /** * 动画效果1 */ - (void)animationEventTypeOne { // 执行隐式动画 _shapeLayer3.strokeEnd = arc4random() % 100 / 100.f; } /** * 动画效果2 */ - (void)animationEventTypeTwo { CGFloat valueOne = arc4random() % 100 / 100.f; CGFloat valueTwo = arc4random() % 100 / 100.f; // 执行隐式动画 _shapeLayer3.strokeStart = valueOne < valueTwo ? valueOne : valueTwo; _shapeLayer3.strokeEnd = valueOne > valueTwo ? valueOne : valueTwo; }
四 贝塞尔曲线 其他方法:
+ (UIBezierPath *)bezierPathWithRect:(CGRect)rect
2,根据矩形框的内切圆画曲线
+ (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect
3,
参数:
center:弧线中心点的坐标
radius:弧线所在圆的半径
startAngle:弧线开始的角度值
endAngle:弧线结束的角度值
clockwise:是否顺时针画弧线
4,
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint
参数:
endPoint:曲线的终点
controlPoint:画曲线的基准点
- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2
参数:
endPoint:曲线的终点
controlPoint1:画曲线的第一个基准点
controlPoint2:画曲线的第二个基准点