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 strokeStartstrokeEnd;

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

/* 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

时间: 2024-09-07 02:46:08

CAShapeLayer的使用[2]的相关文章

[翻译] CKShapeView 支持CAShapeLayer

CKShapeView 支持CAShapeLayer https://github.com/conradev/CKShapeView CKShapeView is a UIView subclass that is backed by a CAShapeLayer. In other words, it is a view that is capable of rendering an arbitrary CGPath. It is completely configurable and ani

用CAShapeLayer写股市K线图动画效果

用CAShapeLayer写股市K线图动画效果   说明 入市有风险,炒股需谨慎.(因项目需求,本人提供了写这种效果的源码)   效果   源码 // // ViewController.m // Path // // Created by YouXianMing on 15/5/11. // Copyright (c) 2015年 YouXianMing. All rights reserved. // #import "ViewController.h" @interface Vi

修改UIView的backedlayer为CAShapeLayer

修改UIView的backedlayer为CAShapeLayer 什么叫backedlayer呢?backedlayer指的是一个View在创建好的时候就已经帮你创建好了一个与View大小一致的CALayer了,而且,这个CALayer的所有属性值的改变都不会引起动画反应,除非写在+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations这个方法里面.认识到这一点是很关键的

放肆地使用UIBezierPath和CAShapeLayer画各种图形

CAShapeLayer 是 CALayer 的子类,但是比 CALayer 更灵活,可以画出各种图形,当然,你也可以使用其他方式来画,随你. 杂谈 在 CAShapeLayer 中,也可以像 CALayer 一样指定它的 frame 来画,就像这样: 1 2 3 4 5 let layer = CAShapeLayer() layer.frame = CGRectMake(110, 100, 150, 100) layer.backgroundColor = UIColor.blackColo

[控件] 动态实时设置CAShapeLayer贝塞尔曲线的坐标点

动态实时设置CAShapeLayer贝塞尔曲线的坐标点 效果图: 源码: PathDirectionView.h 与 PathDirectionView.m // // PathDirectionView.h // Path // // Created by XianMingYou on 15/2/27. // Copyright (c) 2015年 XianMingYou. All rights reserved. // #import <UIKit/UIKit.h> #import &qu

iOS CAShapeLayer精讲

iOS CAShapeLayer精讲 CAShapeLayer继承自CALayer,因此,可使用CALayer的所有属性.但是,CAShapeLayer需要和贝塞尔曲线配合使用才有意义. 关于UIBezierPath,请阅读文章iOS UIBezierPth精讲 基本知识 看看官方说明: /* The shape layer draws a cubic Bezier spline in its coordinate space. * * The spline is described using

关于CAShapeLayer

内容大纲: CAShapeLayer简介 贝塞尔曲线与CAShapeLayer的关系 strokeStart和strokeEnd 动画 用CAShapeLayer实现进度条效果,以及更加复杂的效果 1.CAShapeLayer简介   1.CAShapeLayer继承自CALayer,可以使用CALayer的所有属性值 2.CAShapeLayer需要与贝塞尔曲线配合使用才有意义 3.使用CAShapeLayer与贝塞尔曲线可以实现不在view的drawRect方法中画出有一些想要的图形 4.C

Swift:使用CAShapeLayer打造一个ProgresssBar

ProgressBar是一个很小却在很多地方都会用到的东西.也许是网络连接,也许APP本身有很多东西需要加载的.默认的只有一个旋转的菊花,对于打造一款个性的APP这显然是不够的.这里就使用CAShapeLayer打造一个个性的ProgressBar.这里只是抛砖引玉,你可以在这个基础上开发更适合你的. CAShapeLayer是iOS开发中一个很强的东西,你可以用他开发出各种形状,还可以在上面加动画.所以,CAShapeLayer简直就是创建ProgressBar的完美选择. 这个Progres

CAShapeLayer(持续更新)

CAShapeLayer 之前讲过CALayer动画相关知识,再来看看更加复杂的CAShapeLayer相关的动画知识. 普通CALayer在被初始化时是需要给一个frame值的,这个frame值一般都与给定view的bounds值一致,它本身是有形状的,而且是矩形. CAShapeLayer在初始化时也需要给一个frame值,但是,它本身没有形状,它的形状来源于你给定的一个path,然后它去取CGPath值,它与CALayer有着很大的区别     CAShapeLayer有着几点很重要: 1

iOS 中 CAShapeLayer 的使用( 等待删除的博文)

1.CAShapeLayer 简介 1.CAShapeLayer继承至CALayer,可以使用CALayer的所有属性值 2.CAShapeLayer需要与贝塞尔曲线配合使用才有意义 3.使用CAShapeLayer与贝塞尔曲线可以实现不在view的drawRect方法中画出一些想要的图形 4.CAShapeLayer属于CoreAnimation框架,其动画渲染直接提交到手机的GPU当中,相较于view的drawRect方法使用CPU渲染而言, 其效率极高,能大大优化内存使用情况 效果: 2.