博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
动画-复制层(CAReplicatorLayer)
阅读量:6229 次
发布时间:2019-06-21

本文共 4748 字,大约阅读时间需要 15 分钟。

复制层(CAReplicatorLayer)

对于下面的效果大家是否有实现思路?

有些人可能要说:老夫撸起袖子,敲键盘就是干,不需要手势交互,那么直接用5个CALayer,处理不同的位置以及定时器、透明度等等,貌似很简单。

不不不,今天要带出来的主题是 CAReplicatorLayer

1、CAReplicatorLayer

/* The replicator layer creates a specified number of copies of its

  • sublayers, each copy potentially having geometric, temporal and
  • color transformations applied to it.
  • Note: the CALayer -hitTest: method currently only tests the first
  • instance of z replicator layer's sublayers. This may change in the
  • future. */

官方给出的意思就不翻译了,使用场景大致是一个形状、特性差不多的 layer,我们不需要重复创建,可以利用它来实现复制多个 layer ,然后通过 CAReplicatorLayer 的一些属性实现我们的需求。

上述效果的代码

//创建复制层,因为我们做的多个音量柱变化的动画都是一样的,所以创建了一个复制层,这个复制层可以对里面的 sublayer 进行复制,所以我们不需要重复创建了CAReplicatorLayer *replicatorrLayer = [CAReplicatorLayer layer];replicatorrLayer.frame = CGRectMake(0, 0, self.contentView.frame.size.width, self.contentView.frame.size.height);replicatorrLayer.backgroundColor = [UIColor blackColor].CGColor;self.replicatorrLayer = replicatorrLayer;[self.contentView.layer addSublayer:replicatorrLayer];//创建音量震动条CALayer *layer = [CALayer layer];layer.backgroundColor = [UIColor whiteColor].CGColor;CGFloat width = 30;CGFloat height = 100;layer.bounds = CGRectMake(0, self.contentView.frame.size.height - height, width, height);layer.anchorPoint = CGPointMake(0, 1);layer.position = CGPointMake(0, self.contentView.frame.size.height);[self.contentView.layer addSublayer:layer];//创建音量震动动画CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale.y"];animation.toValue = @0;animation.duration = 1;animation.repeatCount = MAXFLOAT;animation.autoreverses = YES;[layer addAnimation:animation forKey:nil];[replicatorrLayer addSublayer:layer];//* The number of copies to create, including the source object.replicatorrLayer.instanceCount = 6; //复制 sublayer 的个数,包括创建的第一个sublayer 在内的个数replicatorrLayer.instanceDelay = 0.4; //设置动画延迟执行的时间replicatorrLayer.instanceAlphaOffset = -0.15; //设置透明度递减replicatorrLayer.instanceTransform = CATransform3DMakeTranslation(50, 0, 0);复制代码

例子1

这里比较简单了,关键代码

CAReplicatorLayer *replicatorLayer = (CAReplicatorLayer *)self.view.layer;replicatorLayer.instanceCount = 2;replicatorLayer.instanceTransform = CATransform3DMakeRotation(M_PI, 1, 0, 0);replicatorLayer.instanceRedOffset -= 0.1;replicatorLayer.instanceGreenOffset -= 0.1;replicatorLayer.instanceBlueOffset -= 0.1;replicatorLayer.instanceAlphaOffset -= 0.3;复制代码
  • 需要说明是这里我用 storyboard 处理的,因为已经拉好了控件,所以我们没办法将图片直接加到复制层上去。间接做法是将 UIViewController 的 view 的 layer 类型改变为 复制层
//该方法返回 UIView 的层//改写 UIView 的层:重写 layerClass 方法+ (Class)layerClass{return [CAReplicatorLayer class];}复制代码

例子2

需求分析:

  • 先画图。也就是添加一个滑动手势并监听它。然后强制绘图(self setNeedsDisplay)

  • 添加一个 layer 到 self.layer 上

  • 改变当前 view 的 layer 类型。

+ (Class)layerClass{return [CAReplicatorLayer class];}复制代码
  • 设置 CAReplicatorLayer 的 instanceCount 和 instanceDelay 属性

  • 添加了小点,并为小点设置关键帧动画。

  • 重置功能实现靠的是清除 path 上面的 points ,并移除 小点上面的动画

#import "ViewControllerView.h"@interface ViewControllerView()@property (nonatomic, strong) UIBezierPath *path;@property (nonatomic, weak) CALayer *dotLayer;@end@implementation ViewControllerView+ (Class)layerClass{return [CAReplicatorLayer class];}- (void)awakeFromNib{[super awakeFromNib];UIPanGestureRecognizer *tapGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(draw:)];[self addGestureRecognizer:tapGesture];self.path = [UIBezierPath bezierPath];CALayer *layer = [CALayer layer];layer.frame = CGRectMake(-UIScreen.mainScreen.bounds.size.width, 0, 15, 15);layer.backgroundColor = [UIColor orangeColor].CGColor;layer.cornerRadius = 7.5;self.dotLayer = layer;[self.layer addSublayer:layer];CAReplicatorLayer *replicatorLayer = (CAReplicatorLayer *)self.layer;replicatorLayer.instanceCount = 20;replicatorLayer.instanceDelay = 0.25;}- (void)draw:(UIPanGestureRecognizer *)tap{CGPoint currentPoint = [tap locationInView:self];if (tap.state == UIGestureRecognizerStateBegan) {[self.path moveToPoint:currentPoint];}else if(tap.state == UIGestureRecognizerStateChanged){[self.path addLineToPoint:currentPoint];[self setNeedsDisplay];}}- (void)startAnimation{//要实现动画围绕着给定的形状执行,那么需要关键帧动画(类比于Flash概念中的关键帧动画,只需要给定指定的关键帧,其余的帧系统会创建出来。)。关键帧动画的 path 和 values 是互斥的,也就是说如果设置了 values 还设置了 path 那么 path 属性会覆盖 values 属性。CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];animation.keyPath = @"position";animation.path = self.path.CGPath;animation.duration = 5;animation.repeatCount = MAXFLOAT;[self.dotLayer addAnimation:animation forKey:nil];}- (void)redraw{//清空路径:移除 path 上面所有的点,然后重绘[self.path removeAllPoints];[self setNeedsDisplay];//移除动画[self.dotLayer removeAllAnimations];}- (void)drawRect:(CGRect)rect{[self.path stroke];}@end复制代码

CALayer 层的动画有2个概念非常重要:AnchorPoint 和 position

  • postion 用来确定 layer 层在父层中的位置

  • anchorPoint 用来确定 layer 身上哪个点会在 position 所指的位置。

转载地址:http://pcxna.baihongyu.com/

你可能感兴趣的文章
关于访问MSMQ远端私有队列的一点经验
查看>>
前端表单校验插件 jquery.validate.min.js自定义校验规则
查看>>
MySQL系列:高可用架构之MHA
查看>>
python堡垒机开发
查看>>
共享内存
查看>>
关于this
查看>>
用户登录(二次机会)且每次输错误时显示剩余错误次数(提示:使用字符串格式化)...
查看>>
[转载][转帖]谈谈我对攻读计算机研究生的看法。。。大牛的文章,见解精深独到...
查看>>
使用Python进行AES加密和解密
查看>>
Unity_UIWidgets学习笔记03_组件_Image
查看>>
linux cat 命令详解
查看>>
转.给android设备安装busybox
查看>>
Docker swarm集群增加节点和删除节点
查看>>
将 年-月-日 封装成tree树状结构
查看>>
Maximum Depth of Binary Tree
查看>>
DFS
查看>>
UIImageView
查看>>
Dynamic CRM 2013学习笔记(二)插件基本用法及调试
查看>>
c# 报表练习笔记
查看>>
Spark学习之路 (七)Spark 运行流程
查看>>