CAShapeLayer的path动画

简介:

CAShapeLayer的path动画

 

效果

 

源码

https://github.com/YouXianMing/Animations



//
//  CAShapeLayerPathController.m
//  Animations
//
//  Created by YouXianMing on 15/11/17.
//  Copyright © 2015年 YouXianMing. All rights reserved.
//

#import "CAShapeLayerPathController.h"
#import "PathView.h"
#import "UIView+SetRect.h"
#import "GCD.h"

@interface CAShapeLayerPathController ()

@property (nonatomic, strong) PathView *pathView;
@property (nonatomic, strong) GCDTimer *timer;

@property (nonatomic, strong) CAShapeLayer *lineShapeLayer;
@property (nonatomic, strong) CAShapeLayer *fillShapeLayer;

@property (nonatomic) CGPoint A;

@property (nonatomic, strong) CALayer *pointA;

@end

@implementation CAShapeLayerPathController

- (void)viewDidLoad {
    
    [super viewDidLoad];
}

- (void)setup {
    
    [super setup];
    
    // background view
    self.pathView        = [[PathView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
    self.pathView.center = self.view.center;
    self.pathView.gap    = 10.f;
    [self.pathView setNeedsDisplay];
    [self.view addSubview:self.pathView];
    UIBezierPath *path = [self randomPath];
    
    // point A
    self.pointA                 = [CALayer layer];
    self.pointA.frame           = CGRectMake(0, 0, 4, 4);
    self.pointA.cornerRadius    = 2.f;
    self.pointA.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5f].CGColor;
    self.pointA.position        = CGPointMake(self.A.x + 10, self.A.y + 10);
    [self.pathView.layer addSublayer:self.pointA];
    
    // shape
    self.fillShapeLayer             = [CAShapeLayer layer];
    self.fillShapeLayer.path        = path.CGPath;
    self.fillShapeLayer.strokeColor = [UIColor clearColor].CGColor;
    self.fillShapeLayer.fillColor   = [UIColor cyanColor].CGColor;
    self.fillShapeLayer.lineWidth   = 0.f;
    self.fillShapeLayer.frame       = CGRectMake(self.pathView.gap,
                                                 self.pathView.gap,
                                                 self.pathView.width - 2 * self.pathView.gap,
                                                 self.pathView.width - 2 * self.pathView.gap);
    [self.pathView.layer addSublayer:self.fillShapeLayer];

    // line
    self.lineShapeLayer             = [CAShapeLayer layer];
    self.lineShapeLayer.path        = path.CGPath;
    self.lineShapeLayer.strokeColor = [UIColor redColor].CGColor;
    self.lineShapeLayer.fillColor   = [UIColor clearColor].CGColor;
    self.lineShapeLayer.lineWidth   = 0.5f;
    self.lineShapeLayer.lineDashPattern = @[@(3), @(3)];
    self.lineShapeLayer.frame       = CGRectMake(self.pathView.gap,
                                                 self.pathView.gap,
                                                 self.pathView.width - 2 * self.pathView.gap,
                                                 self.pathView.width - 2 * self.pathView.gap);
    [self.pathView.layer addSublayer:self.lineShapeLayer];
    
    // timer
    self.timer = [[GCDTimer alloc] initInQueue:[GCDQueue mainQueue]];
    [self.timer event:^{
        
        // path animation.
        UIBezierPath *newPath            = [self randomPath];
        CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
        basicAnimation.duration          = 0.5;
        basicAnimation.fromValue         = (__bridge id)(self.lineShapeLayer.path);
        basicAnimation.toValue           = (__bridge id)newPath.CGPath;
        self.lineShapeLayer.path         = newPath.CGPath;
        self.fillShapeLayer.path         = newPath.CGPath;
        [self.lineShapeLayer addAnimation:basicAnimation forKey:@"lineShapeLayerPath"];
        [self.fillShapeLayer addAnimation:basicAnimation forKey:@"fillShapeLayerPath"];
        
        // fillColor animation.
        UIColor *newColor = [self randomColor];
        CABasicAnimation *colorAnimation = [CABasicAnimation animationWithKeyPath:@"fillColor"];
        colorAnimation.duration          = 0.5;
        colorAnimation.fromValue         = (__bridge id _Nullable)(self.fillShapeLayer.fillColor);
        colorAnimation.toValue           = (__bridge id)newColor.CGColor;
        self.fillShapeLayer.fillColor    = newColor.CGColor;
        [self.fillShapeLayer addAnimation:colorAnimation forKey:@"fillShapeLayerColor"];
        
        // path animation.
        CGPoint newPoint = CGPointMake(self.A.x + 10, self.A.y + 10);
        CABasicAnimation *positionAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
        positionAnimation.duration          = 0.5f;
        positionAnimation.fromValue         = [NSValue valueWithCGPoint:self.pointA.position];
        positionAnimation.toValue           = [NSValue valueWithCGPoint:newPoint];
        self.pointA.position                = newPoint;
        [self.pointA addAnimation:positionAnimation forKey:@"positionAnimation"];
        
    } timeIntervalWithSecs:1.f];
    [self.timer start];
}

- (UIBezierPath *)randomPath {
    
    CGPoint pointA = [self randomPointA];
    CGPoint pointB = [self randomPointB];
    CGPoint pointC = [self randomPointC];
    CGPoint pointD = [self randomPointD];
    
    self.A = pointA;
    
    UIBezierPath* bezierPath = [UIBezierPath bezierPath];
    [bezierPath moveToPoint:pointA];
    [bezierPath addLineToPoint:pointB];
    [bezierPath addLineToPoint:pointC];
    [bezierPath addLineToPoint:pointD];
    [bezierPath closePath];
    
    return bezierPath;
}

- (CGPoint)randomPointA {
    
    return CGPointMake(arc4random() % (int)(self.pathView.width - 2 * self.pathView.gap), 0);
}

- (CGPoint)randomPointB {
    
    return CGPointMake(self.pathView.width - 2 * self.pathView.gap, arc4random() % (int)(self.pathView.width - 2 * self.pathView.gap));
}

- (CGPoint)randomPointC {
    
    return CGPointMake(arc4random() % (int)(self.pathView.width - 2 * self.pathView.gap), self.pathView.width - 2 * self.pathView.gap);
}

- (CGPoint)randomPointD {
    
    return CGPointMake(0, arc4random() % (int)(self.pathView.width - 2 * self.pathView.gap));
}

- (UIColor *)randomColor {
    
    return [UIColor colorWithRed:arc4random() % 101 / 100.f
                           green:arc4random() % 101 / 100.f
                            blue:arc4random() % 101 / 100.f
                           alpha:0.5f];
}

@end

细节

注意keyPath参数。

 

目录
相关文章
SVG SMIL 动画(基本动画 、变换动画)
SVG SMIL 动画(基本动画 、变换动画)
61 0
|
前端开发
用canvas绘制一个烟花动画
前言 在我们日常开发中贝塞尔曲线无处不在: svg 中的曲线(支持 2阶、 3阶) canvas 中绘制贝塞尔曲线 几乎所有前端2D或3D图形图表库(echarts,d3,three.js)都会使用到贝塞尔曲线 所以掌握贝塞尔曲线势在必得。这篇文章主要是实战篇,不会介绍和贝塞尔相关的知识, 如果有同学对贝塞尔曲线不是很清楚的话:可以查看我这篇文章——深入理解SVG 绘制贝塞尔曲线 第一步我们先创建ctx, 用ctx 画一个二阶贝塞尔曲线看下。二阶贝塞尔曲线有1个控制点,一个起点,一个终点。 const canvas = document.getElementById( 'canvas'
用canvas绘制一个烟花动画
CABasicAnimation旋转动画
CABasicAnimation旋转动画
186 0
CABasicAnimation旋转动画
|
XML Android开发 数据格式
Animations动画和Keyframes关键帧
Title body { display: flex; /* 使用Flex布局 */ justify-content: center; /* 水平居中 */ } .
850 0
|
UED 缓存 异构计算
UIImageView添加圆角的几种方法
喜欢我的可以关注收藏我的个人博客:RobberJJ 创建一个UIImageView对象: UIImageView * poImgView = [[UIImageView alloc] init]; 第一种方法 poImgView.
968 0
|
XML Android开发 数据格式
Android动画Frame Animation 帧动画
//=================【frame animation 帧动画】=============================== Frame动画是一系列图片按照一定的顺序展示的过程,和放电影的机制很相似,我们称为逐帧动画。 Frame动画可以被定义在XML文件中,也可以完全编码实现。 实现方法两种: 1)xml中的实现方法在/res下的anim或drawable目
1551 0