• CAShapeLayer实现圆形进度条效果


    一、CAShapeLayer简单介绍:

    1CAShapeLayer继承至CALayer,能够使用CALayer的全部属性值

    2CAShapeLayer须要与贝塞尔曲线配合使用才有意义

    3、使用CAShapeLayer与贝塞尔曲线能够实现不在viewdrawRect方法中画出一些想要的图形

    4CAShapeLayer属于CoreAnimation框架,其动画渲染直接提交到手机的GPU其中,相较于viewdrawRect方法使用CPU渲染而言,其效率极高,能大大优化内存使用情况


    五角星动画

    #import "ViewController.h"


    @interface ViewController ()


    @property (nonatomic,strong) NSTimer      *timer;

    @property (nonatomic,strong) CAShapeLayer *shapeLayer;


    @end


    @implementation ViewController


    - (void)viewDidLoad {

        [superviewDidLoad];

        

        // 创建shapeLayer

        _shapeLayer = [CAShapeLayerlayer];

        _shapeLayer.frame         = (CGRect){CGPointMake(0,0), CGSizeMake(200,200)};

        _shapeLayer.position      =self.view.center;

        _shapeLayer.path          = [selfgetStar1BezierPath].CGPath;

        _shapeLayer.fillColor     = [UIColorclearColor].CGColor;

        _shapeLayer.strokeColor   = [UIColorredColor].CGColor;

        _shapeLayer.lineWidth     =2.f;

        [self.view.layeraddSublayer:_shapeLayer];

        

        // 创建定时器

        _timer = [NSTimerscheduledTimerWithTimeInterval:1.f

                                                 target:self

                                               selector:@selector(pathAnimation)

                                               userInfo:nil

                                                repeats:YES];

    }


    /**

     *  运行path的动画

     */

    - (void)pathAnimation {

        static int i =0;

        if (i++ % 2 ==0) {

            CABasicAnimation *circleAnim = [CABasicAnimationanimationWithKeyPath:@"path"];

            circleAnim.removedOnCompletion =NO;

            circleAnim.duration            =1;

            circleAnim.fromValue           = (__bridgeid)[self getStar1BezierPath].CGPath;

            circleAnim.toValue             = (__bridgeid)[self getStar2BezierPath].CGPath;

            _shapeLayer.path               = [selfgetStar2BezierPath].CGPath;

            [_shapeLayeraddAnimation:circleAnim forKey:@"animateCirclePath"];

        }else {

            CABasicAnimation *circleAnim = [CABasicAnimationanimationWithKeyPath:@"path"];

            circleAnim.removedOnCompletion =NO;

            circleAnim.duration            =1;

            circleAnim.fromValue           = (__bridgeid)[self getStar2BezierPath].CGPath;

            circleAnim.toValue             = (__bridgeid)[self getStar1BezierPath].CGPath;

            _shapeLayer.path               = [selfgetStar1BezierPath].CGPath;

            [_shapeLayeraddAnimation:circleAnim forKey:@"animateCirclePath"];

        }

    }


    /**

     *  贝塞尔曲线1

     *

     *  @return 贝塞尔曲线

     */

    -(UIBezierPath *)getStar1BezierPath {

        //// Star Drawing

        UIBezierPath* starPath = [UIBezierPathbezierPath];

        [starPathmoveToPoint: 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)];

        [starPathclosePath];

        

        return starPath;

    }


    /**

     *  贝塞尔曲线2

     *

     *  @return 贝塞尔曲线

     */

    -(UIBezierPath *)getStar2BezierPath {

        //// Star Drawing

        UIBezierPath* starPath = [UIBezierPathbezierPath];

        [starPathmoveToPoint: 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)];

        [starPathclosePath];

        

        return starPath;

    }


    @end



    二、贝塞尔曲线与CAShapeLayer的关系

    1CAShapeLayer中有Shape这个单词。顾名思义,它须要一个形状才干生效

    2、贝塞尔曲线能够创建基于矢量的路径

    3、贝塞尔曲线给CAShapeLayer提供路径。CAShapeLayer在提供的路径中进行渲染。路径会闭环,所以路径绘制出了Shape

    4、用于CAShapeLayer的贝塞尔曲线作为path,其path是一个首尾相接的闭环的曲线,即使该贝塞尔曲线不是一个闭环的曲线


    注意:shapeframe 要大于BezierPathframe.BezierPath不会由于shareframe而拉升。否则BezierPath截断

    - (void)viewDidLoad {

        [superviewDidLoad];

        

        //创建椭圆形贝塞尔曲线

        UIBezierPath *oval = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0, 200,100)];

        

        //创建矩形贝塞尔曲线

        UIBezierPath *rect = [UIBezierPathbezierPathWithRect:CGRectMake(0,0, 200,100)];

        

        //创建圆形贝塞尔曲线

        UIBezierPath *circle = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0, 100,100)];

        

        // 创建CAShapeLayer

        CAShapeLayer *shape = [CAShapeLayerlayer];

        shape.frame         =CGRectMake(0,0, 200, 50);

        shape.position      =self.view.center;

        

        // 显示CAShapeLayer的边界

        shape.borderWidth   =1.f;

        

        // 禁止内容显示超出CAShapeLayerframe

        shape.masksToBounds =YES;

        

        //改动贝塞尔曲线的填充颜色

        shape.fillColor     = [UIColorredColor].CGColor;

        

        // 建立贝塞尔曲线与CAShapeLayer之间的关联

        shape.path = circle.CGPath;

        

        // 加入并显示

        [self.view.layeraddSublayer:shape];

    }


    三、StrokeStartStrokeEnd动画

    1、将ShapeLayerfillColor设置成透明背景

    2、设置线条的宽度(lineWidth)的值

    3、设置线条的颜色

    4、将strokeStart值设定成0,然后让strokeEnd的值变化触发隐式动画

    @interface ViewController ()

    @property (nonatomic,strong) NSTimer      *timer;     // 定时器

    @property (nonatomic,strong) CAShapeLayer *shapeLayer;// 形状layer

    @end


    @implementation ViewController


    - (void)viewDidLoad {

        [superviewDidLoad];

        

        // 设置背景色

        self.view.backgroundColor = [UIColorcolorWithRed:0.878green:0.878blue:0.878alpha:1];

        

        //创建椭圆形贝塞尔曲线

        UIBezierPath *oval        = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0, 100,100)];

        

        // 创建CAShapeLayer

        _shapeLayer               = [CAShapeLayerlayer];

        _shapeLayer.frame         =CGRectMake(0,0, 100, 100);

        _shapeLayer.position      =self.view.center;

        

        // 改动CAShapeLayer的线条相关值

        _shapeLayer.fillColor     = [UIColorclearColor].CGColor;

        _shapeLayer.strokeColor   = [UIColorredColor].CGColor;

        _shapeLayer.lineWidth     =2.f;

        _shapeLayer.strokeStart   =0.f;

        _shapeLayer.strokeEnd     =0.f;

        

        // 建立贝塞尔曲线与CAShapeLayer之间的关联

        _shapeLayer.path          = oval.CGPath;

        

        // 加入并显示

        [self.view.layeraddSublayer:_shapeLayer];

        

        // 创建定时器

        _timer = [NSTimerscheduledTimerWithTimeInterval:1.f

                                                 target:self

                                               selector:@selector(animationEventTypeTwo)

                                               userInfo:nil

                                                repeats:YES];

    }


    /**

     *  动画效果1

     */

    - (void)animationEventTypeOne {

        // 运行隐式动画

        _shapeLayer.strokeEnd =arc4random() % 100 /100.f;

    }


    /**

     *  动画效果2

     */

    - (void)animationEventTypeTwo {

        CGFloat valueOne = arc4random() % 100 / 100.f;

        CGFloat valueTwo = arc4random() % 100 / 100.f;

        // storkeStar storkeEnd同一时候赋值。strokeStart要小于strokeEnd的值

        // 运行隐式动画

        _shapeLayer.strokeStart = valueOne < valueTwo ?

    valueOne : valueTwo;

        _shapeLayer.strokeEnd   = valueOne > valueTwo ?

    valueOne : valueTwo;

    }


    @end




    四、用CAShapeLayer实现圆形进度条效果

    1、确定须要设定的參数

    2、实现细节

    3、进行測试

    @interface CircleView :UIView


    @property (nonatomic,assign) CGFloat  startValue;// 起始值(0~1

    @property (nonatomic,assign) CGFloat  lineWidth; // 线宽(>0)

    @property (nonatomic,strong) UIColor *lineColor; // 线条颜色

    @property (nonatomic,assign) CGFloat  value;     // 变化的值


    @end


    #import "CircleView.h"


    @interface CircleView ()


    @property (nonatomic,strong) CAShapeLayer *shapeLayer;


    @end


    @implementation CircleView


    - (instancetype)initWithFrame:(CGRect)frame {

        self = [superinitWithFrame:frame];

        if (self) {

            // 创建出CAShapeLayer

            _shapeLayer       = [CAShapeLayerlayer];

            _shapeLayer.frame =self.bounds;

            

            // 创建出贝塞尔曲线

            UIBezierPath *path = [UIBezierPathbezierPathWithOvalInRect:self.bounds];

            

            // 贝塞尔曲线与CAShapeLayer产生关联

            _shapeLayer.path = path.CGPath;

            

            // 基本配置

            _shapeLayer.fillColor   = [UIColorclearColor].CGColor;

            _shapeLayer.lineWidth   =1.f;

            _shapeLayer.strokeColor = [UIColorredColor].CGColor;

            _shapeLayer.strokeEnd   =0.f;

            

            // 加入到当前view

            [self.layeraddSublayer:_shapeLayer];

        }

        return self;

    }


    @synthesize startValue =_startValue;

    - (void)setStartValue:(CGFloat)startValue {

        _startValue           = startValue;

        _shapeLayer.strokeEnd = startValue;

    }

    - (CGFloat)startValue {

        return_startValue;

    }


    @synthesize lineWidth =_lineWidth;

    - (void)setLineWidth:(CGFloat)lineWidth {

        _lineWidth            = lineWidth;

        _shapeLayer.lineWidth = lineWidth;

    }

    - (CGFloat)lineWidth {

        return_lineWidth;

    }


    @synthesize lineColor =_lineColor;

    - (void)setLineColor:(UIColor *)lineColor {

        _lineColor              = lineColor;

        _shapeLayer.strokeColor = lineColor.CGColor;

    }

    - (UIColor *)lineColor {

        return_lineColor;

    }


    @synthesize value = _value;

    - (void)setValue:(CGFloat)value {

        _value                = value;

        _shapeLayer.strokeEnd = value;

    }

    - (CGFloat)value {

        return _value;

    }


    @end


    #import "CircleView.h"


    @interface ViewController ()


    {

        CircleView *circle;

    }


    @end


    @implementation ViewController


    - (void)viewDidLoad {

        [superviewDidLoad];

        

        circle             = [[CircleViewalloc] initWithFrame:CGRectMake(0,0, 200, 200)];

        circle.center      =self.view.center;

        circle.startValue  =0.5;

        circle.lineWidth   =3.f;

        circle.lineColor   = [UIColorgrayColor];

        [self.viewaddSubview:circle];

        

        [selfperformSelector:@selector(delayAnimation)

                  withObject:nil

                  afterDelay:3.f];

    }


    - (void)delayAnimation {

        circle.value =1.f;

    }


    @end


  • 相关阅读:
    每天一个设计模式(2):观察者模式
    每天一个设计模式(1):策略模式
    每天一个设计模式(0):设计模式概述
    常量池、栈、堆的比较
    常量池小结
    Java虚拟机体系结构分析
    Java并发(3):volatile及Java内存模型
    第一题:Big Countries
    22 高级SQL特性
    21 使用游标
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/7240792.html
Copyright © 2020-2023  润新知