CAGradientLayer与CAShapeLayer实现不同颜色画圆动画(Spark相机的录制的效果)

<pre name="code" class="objc">可以适当加以封装,参考网址http://www.cocoachina.com/industry/20140705/9039.html
//
//  ViewController.m
//  CircleAnimationDemo
//
//  Created by 程磊 on 15/5/3.
//  Copyright (c) 2015年 程磊. All rights reserved.
//

#import "ViewController.h"
#define APP_WIDTH [UIScreen mainScreen].bounds.size.width
#define APP_HEIGHT [UIScreen mainScreen].bounds.size.height

@interface ViewController ()

@property (nonatomic, strong) CAShapeLayer *currentProgressLayer;//当前的layer

@property (nonatomic, assign) CGFloat duration;//完成一圈动画需要的时间

@property (nonatomic, strong) NSMutableArray *progressLayers;//存放后加入的layer

@property (nonatomic, strong) UIBezierPath *circlePath;//贝塞尔曲线轨迹

@property (nonatomic, assign) CGFloat strokeWidth;//线条宽度

@property (nonatomic, strong) CAShapeLayer *backgroundLayer;//北京layer

@property (nonatomic, assign) BOOL isCircleComplete;//是否完成

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    _duration = 45;
    _strokeWidth = 6;
    _progressLayers = [[NSMutableArray alloc] init];
    _backgroundLayer = [CAShapeLayer layer];
    _backgroundLayer.frame = CGRectMake(0, 0, 200, 200);
    _backgroundLayer.position = CGPointMake((APP_WIDTH-200)/2, 100);
    _backgroundLayer.anchorPoint = CGPointMake(0, 0);
    _backgroundLayer.fillColor = [UIColor clearColor].CGColor;
    _backgroundLayer.strokeColor = [UIColor lightGrayColor].CGColor;
    _backgroundLayer.lineWidth = self.strokeWidth;
    [self.view.layer addSublayer:_backgroundLayer];
    _backgroundLayer.strokeStart = 0;
    _backgroundLayer.strokeEnd = 1;
    _circlePath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 200, 200)];
    _backgroundLayer.path = _circlePath.CGPath;
    
}

/**
 *  添加新的shapeLayer
 *
 */
- (void)addNewLayerstroke
{
    CAShapeLayer *progressLayer = [CAShapeLayer layer];
    progressLayer.path = self.circlePath.CGPath;
    progressLayer.position = CGPointMake((APP_WIDTH-200)/2, 100);
    progressLayer.anchorPoint = CGPointMake(0, 0);
    progressLayer.strokeColor = [[self randomColor] CGColor];
    progressLayer.fillColor = [[UIColor clearColor] CGColor];
    progressLayer.lineWidth = 6.f;
    progressLayer.strokeEnd = 0.f;
    
    [self.view.layer addSublayer:progressLayer];
    [self.progressLayers addObject:progressLayer];
    
    self.currentProgressLayer = progressLayer;
}

/**
 *  随机色
 *
 */
- (UIColor *)randomColor {
    return [UIColor colorWithRed:arc4random() % 256 / 256.f
                           green:arc4random() % 256 / 256.f
                            blue:arc4random() % 256 / 256.f
                           alpha:1];
}

/**
 *  执行动画
 *  上面代码中我们看到我们遍历了所有的CAShapeLayer,给每个strokeEnd添加了CABasicAnimation动画,然后给不是当前的layer的strokeStart属性添加了一个动画。再来看看duration,假设一圈代表45秒钟,这个意味着每次停止之后又开始的话duration肯定是减少的,所以用duration代表一圈剩余的可以录制的时间,再看strekeEndFinal,假设有很多段,肯定不是每个段的strkeEnd都是1所以这个是用来标识每段可以达到的最终距离一圈为(0-1)。最后我们需要更新background layer除去有彩色段剩余的地方。
 你可能注意到上面的代码里面并没有移除动画,所以对于显示每一个CAShapeLayer我们设置都是通过layers的presentationLayer设置strokeStart和strokeEnd,然后移除CAShapeLayer上的所有动画。
 
 presentationLayer在文档中是这么说的:
 
 “While an animation is in progress, you can retrieve this object and use it to get the current values for those animations.”
 */
- (void)updateAnimations
{
    CGFloat duration = self.duration * (1.f - [[self.progressLayers firstObject] strokeEnd]);//获取当前的执行动画需要的时间
    CGFloat strokeEndFinal = 1.f;
    
    for (CAShapeLayer *progressLayer in self.progressLayers)
    {
        CABasicAnimation *strokeEndAnimation = nil;
        strokeEndAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
        strokeEndAnimation.duration = duration;
        strokeEndAnimation.fromValue = @(progressLayer.strokeEnd);
        strokeEndAnimation.toValue = @(strokeEndFinal);
        strokeEndAnimation.autoreverses = NO;
        strokeEndAnimation.repeatCount = 0.f;
        
        CGFloat previousStrokeEnd = progressLayer.strokeEnd;
        progressLayer.strokeEnd = strokeEndFinal;
        
        [progressLayer addAnimation:strokeEndAnimation forKey:@"strokeEndAnimation"];
        
        strokeEndFinal -= (previousStrokeEnd - progressLayer.strokeStart);
        
        if (progressLayer != self.currentProgressLayer)
        {
            CABasicAnimation *strokeStartAnimation = nil;
            strokeStartAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
            strokeStartAnimation.duration = duration;
            strokeStartAnimation.fromValue = @(progressLayer.strokeStart);
            strokeStartAnimation.toValue = @(strokeEndFinal);
            strokeStartAnimation.autoreverses = NO;
            strokeStartAnimation.repeatCount = 0.f;
            
            progressLayer.strokeStart = strokeEndFinal;
            
            [progressLayer addAnimation:strokeStartAnimation forKey:@"strokeStartAnimation"];
        }
    }
    
    CABasicAnimation *backgroundLayerAnimation = nil;
    backgroundLayerAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
    backgroundLayerAnimation.duration = duration;
    backgroundLayerAnimation.fromValue = @(self.backgroundLayer.strokeStart);
    backgroundLayerAnimation.toValue = @(1.f);
    backgroundLayerAnimation.autoreverses = NO;
    backgroundLayerAnimation.repeatCount = 0.f;
    backgroundLayerAnimation.delegate = self;
    
    self.backgroundLayer.strokeStart = 1.0;
    
    [self.backgroundLayer addAnimation:backgroundLayerAnimation forKey:@"strokeStartAnimation"];
}



/**
 *  点击开始响应事件
 *
 */
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if (self.isCircleComplete == NO) {
        [self addNewLayerstroke];
        [self updateAnimations];
    }
}

/**
 *  触摸结束时调用事件
 *
 */
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    if (self.isCircleComplete == NO) {
        [self removeAnimations];
    }
}

- (void)removeAnimations
{
    for (CAShapeLayer *progressLayer in self.progressLayers)
    {
        progressLayer.strokeStart = [progressLayer.presentationLayer strokeStart];
        progressLayer.strokeEnd = [progressLayer.presentationLayer strokeEnd];
        [progressLayer removeAllAnimations];
    }
    self.backgroundLayer.strokeStart = [self.backgroundLayer.presentationLayer strokeStart];
    [self.backgroundLayer removeAllAnimations];
}


- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    if (self.isCircleComplete == NO && flag)
    {
        [self removeAnimations];
        self.isCircleComplete = flag;
    }
}

@end


 

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值