码迷,mamicode.com
首页 > 其他好文 > 详细

CAShapeLayer实现圆形进度条效果

时间:2015-07-18 00:34:15      阅读:201      评论:0      收藏:0      [点我收藏+]

标签: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 {

    [super viewDidLoad];

    

    // 创建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;

}


@end



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

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

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

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

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


注意:shape的frame 要大于BezierPath的frame.BezierPath不会因为share的frame而拉升,否则BezierPath截断

- (void)viewDidLoad {

    [super viewDidLoad];


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

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

    

    // 创建矩形贝塞尔曲线

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

    

    // 创建圆形贝塞尔曲线

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

    

    // 创建CAShapeLayer

    CAShapeLayer *shape = [CAShapeLayer layer];

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

    shape.position      = self.view.center;

    

    // 显示CAShapeLayer的边界

    shape.borderWidth   = 1.f;

    

    // 禁止内容显示超出CAShapeLayerframe

    shape.masksToBounds = YES;

    

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

    shape.fillColor     = [UIColor redColor].CGColor;

    

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

    shape.path = circle.CGPath;

    

    // 添加并显示

    [self.view.layer addSublayer: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 {

    [super viewDidLoad];

    

    // 设置背景色

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


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

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

    

    // 创建CAShapeLayer

    _shapeLayer               = [CAShapeLayer layer];

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

    _shapeLayer.position      = self.view.center;

    

    // 修改CAShapeLayer的线条相关值

    _shapeLayer.fillColor     = [UIColor clearColor].CGColor;

    _shapeLayer.strokeColor   = [UIColor redColor].CGColor;

    _shapeLayer.lineWidth     = 2.f;

    _shapeLayer.strokeStart   = 0.f;

    _shapeLayer.strokeEnd     = 0.f;


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

    _shapeLayer.path          = oval.CGPath;

    

    // 添加并显示

    [self.view.layer addSublayer:_shapeLayer];

    

    // 创建定时器

    _timer = [NSTimer scheduledTimerWithTimeInterval: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 = [super initWithFrame:frame];

    if (self) {

        // 创建出CAShapeLayer

        _shapeLayer       = [CAShapeLayer layer];

        _shapeLayer.frame = self.bounds;

        

        // 创建出贝塞尔曲线

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

        

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

        _shapeLayer.path = path.CGPath;

        

        // 基本配置

        _shapeLayer.fillColor   = [UIColor clearColor].CGColor;

        _shapeLayer.lineWidth   = 1.f;

        _shapeLayer.strokeColor = [UIColor redColor].CGColor;

        _shapeLayer.strokeEnd   = 0.f;

        

        // 添加到当前view

        [self.layer addSublayer:_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 {

    [super viewDidLoad];


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

    circle.center      = self.view.center;

    circle.startValue  = 0.5;

    circle.lineWidth   = 3.f;

    circle.lineColor   = [UIColor grayColor];

    [self.view addSubview:circle];

    

    [self performSelector:@selector(delayAnimation)

               withObject:nil

               afterDelay:3.f];

}


- (void)delayAnimation {

    circle.value = 1.f;

}


@end




版权声明:本文为博主原创文章,未经博主允许不得转载。

CAShapeLayer实现圆形进度条效果

标签:cashapelayer实现圆形进度条效

原文地址:http://blog.csdn.net/baitxaps/article/details/46933917

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!