• CAShapeLayer的使用[2]


    CAShapeLayer的使用[2]

    CAShapeLayer支持的动画类型有如下这些.

    ------------------------------------------------------------------------------

    /* The path defining the shape to be rendered. If the path extends
     * outside the layer bounds it will not automatically be clipped to the
     * layer, only if the normal layer masking rules cause that. Defaults
     * to null. Animatable. (Note that although the path property is
     * animatable, no implicit animation will be created when the property
     * is changed.) */

    @property CGPathRef path;

    ------------------------------------------------------------------------------

    /* The color to fill the path's stroked outline, or nil for no stroking.
     * Defaults to nil. Animatable. */

    @property CGColorRef strokeColor;

    ------------------------------------------------------------------------------

    /* These values define the subregion of the path used to draw the
     * stroked outline. The values must be in the range [0,1] with zero
     * representing the start of the path and one the end. Values in
     * between zero and one are interpolated linearly along the path
     * length. strokeStart defaults to zero and strokeEnd to one. Both are
     * animatable. */

    @property CGFloat strokeStart, strokeEnd;

    ------------------------------------------------------------------------------

    /* The line width used when stroking the path. Defaults to one.
     * Animatable. */

    @property CGFloat lineWidth;
    ------------------------------------------------------------------------------
    /* The miter limit used when stroking the path. Defaults to ten.
     * Animatable. */

    @property CGFloat miterLimit;

    ------------------------------------------------------------------------------

    /* The phase of the dashing pattern applied when creating the stroke.
     * Defaults to zero. Animatable. */

    @property CGFloat lineDashPhase;

    ------------------------------------------------------------------------------

    现在来尝试path动画,结果如下:

    首先用工具生成path源码:

    源码:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        // shapeLayer
        CAShapeLayer *circleLayer = [CAShapeLayer layer];
        circleLayer.frame         = (CGRect){CGPointMake(0, 0), CGSizeMake(200, 200)};
        circleLayer.position      = self.view.center;
        circleLayer.path          = [self getStar1BezierPath].CGPath;
        circleLayer.fillColor     = [UIColor clearColor].CGColor;
        circleLayer.strokeColor   = [UIColor redColor].CGColor;
        circleLayer.lineWidth     = 2.f;
        [self.view.layer addSublayer:circleLayer];
        
        // 定时器
        _timer = [[GCDTimer alloc] initInQueue:[GCDQueue mainQueue]];
        [_timer event:^{
            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;
                circleLayer.path = [self getStar2BezierPath].CGPath;
                [circleLayer 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;
                circleLayer.path = [self getStar1BezierPath].CGPath;
                [circleLayer addAnimation:circleAnim forKey:@"animateCirclePath"];
            }
        } timeInterval:NSEC_PER_SEC];
        [_timer start];
    }
    
    -(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;
    }
    
    -(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;
    }

    CALayer中有一个令人抽搐的属性叫mask,据说可以做动画,官方文档上说可以:

    但其属性说明中根本就没有animatable字眼.

    /* A layer whose alpha channel is used as a mask to select between the
     * layer's background and the result of compositing the layer's
     * contents with its filtered background. Defaults to nil. When used as
     * a mask the layer's `compositingFilter' and `backgroundFilters'
     * properties are ignored. When setting the mask to a new layer, the
     * new layer must have a nil superlayer, otherwise the behavior is
     * undefined. */

    @property(retain) CALayer *mask;

    这是个bug哦:).

    将CAShapeLayer当做mask做动画的效果:

    源码:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        // shapeLayer
        CAShapeLayer *circleLayer = [CAShapeLayer layer];
        circleLayer.frame         = (CGRect){CGPointMake(0, 0), CGSizeMake(200, 200)};
        circleLayer.position      = self.view.center;
        circleLayer.path          = [self getStar1BezierPath].CGPath;
        circleLayer.fillColor     = [UIColor blackColor].CGColor;
        circleLayer.strokeColor   = [UIColor redColor].CGColor;
        circleLayer.lineWidth     = 2.f;
        
        // backgroundLayer
        CALayer *layer = [CALayer layer];
        layer.frame    = self.view.bounds;
        layer.contents = (__bridge id)([UIImage imageNamed:@"psb.jpg"].CGImage);
        layer.mask     = circleLayer;
        [self.view.layer addSublayer:layer];
        
        // 定时器
        _timer = [[GCDTimer alloc] initInQueue:[GCDQueue mainQueue]];
        [_timer event:^{
            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;
                circleLayer.path = [self getStar2BezierPath].CGPath;
                [circleLayer 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;
                circleLayer.path = [self getStar1BezierPath].CGPath;
                [circleLayer addAnimation:circleAnim forKey:@"animateCirclePath"];
            }
        } timeInterval:NSEC_PER_SEC];
        [_timer start];
    }
    
    -(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;
    }
    
    -(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与贝塞尔曲线一起制作下载进度条是相当的容易的说:

    //
    //  RootViewController.m
    //
    //  Copyright (c) 2014年 Y.X. All rights reserved.
    //

    #import "RootViewController.h"
    #import "YXGCD.h"

    @interface RootViewController ()

    @property (nonatomic, strong) GCDTimer *timer;

    @end

    @implementation RootViewController


    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        // 获取path
        UIBezierPath *path = [self getBezierPathWithLength:300 lineWidth:1];
        
        // shapeLayer
        CAShapeLayer *circleLayer = [CAShapeLayer layer];
        circleLayer.frame         = path.bounds;
        circleLayer.position      = self.view.center;
        circleLayer.fillColor     = [UIColor clearColor].CGColor;
        circleLayer.strokeColor   = [UIColor redColor].CGColor;
        circleLayer.path          = path.CGPath;
        circleLayer.lineWidth     = 1.f;
        [self.view.layer addSublayer:circleLayer];
        
        // 定时器
        _timer = [[GCDTimer alloc] initInQueue:[GCDQueue mainQueue]];
        [_timer event:^{

            circleLayer.strokeEnd = arc4random()%100/100.f;
            
        } timeInterval:NSEC_PER_SEC];
        [_timer start];
    }

    -(UIBezierPath *)getBezierPathWithLength:(CGFloat)length lineWidth:(CGFloat)lineWidth
    {
        //// Bezier Drawing
        UIBezierPath* bezierPath = [UIBezierPath bezierPath];
        [bezierPath moveToPoint: CGPointMake(0, 0)];
        [bezierPath addLineToPoint: CGPointMake(length, 0)];
        bezierPath.lineWidth = lineWidth;
        
        return bezierPath;
    }

    @end

     

  • 相关阅读:
    燕之屋燕窝被指97%为糖水和增稠剂 营养价值不如鸡蛋
    烧烤需要准备些什么东西?烧烤步骤
    烧烤材料清单都有什么?
    西雅图华人码农生存实录
    【读书】李建:《读书的“有用”与“无用”》
    孩子,我为什么要求你读书
    读书和不读书差别在哪里?
    招人不是HR第一职责,留住人才是
    select 可输入的下拉框
    toLocaleString 日期
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/3781191.html
Copyright © 2020-2023  润新知