zoukankan      html  css  js  c++  java
  • CAShapeLayer 与贝塞尔曲线

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

    四   贝塞尔曲线 其他方法:

    1,根据一个矩形画曲线

         + (UIBezierPath *)bezierPathWithRect:(CGRect)rect

    2,根据矩形框的内切圆画曲线

    + (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect

    3,

    //以某个中心点画弧线
    + (UIBezierPath *)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;

    参数:

    center:弧线中心点的坐标

    radius:弧线所在圆的半径

    startAngle:弧线开始的角度值

    endAngle:弧线结束的角度值

    clockwise:是否顺时针画弧线

    4,

    //画二元曲线,一般和moveToPoint配合使用

    - (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint

    参数:

    endPoint:曲线的终点

    controlPoint:画曲线的基准点

    //以三个点画一段曲线,一般和moveToPoint配合使用

    - (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2

    参数:

    endPoint:曲线的终点

    controlPoint1:画曲线的第一个基准点

    controlPoint2:画曲线的第二个基准点

  • 相关阅读:
    MySQL 索引优化指南
    Servlet,Tomcat,Jetty,Netty,Mina 对比
    Linux 磁盘IO速度测试
    flume 数据链路问题排查
    MySQL 强行kill后启动失败问题:[ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
    hdfs web界面介绍
    python2/python3 编码问题
    Spark WARN Utils: Service 'sparkDriver' could not bind on port 0. Attempting port 1.
    python2 升级到 python3
    万维网的信息检索系统【计算机网络】
  • 原文地址:https://www.cnblogs.com/developer-qin/p/4534422.html
Copyright © 2011-2022 走看看