神奇的CAReplicatorLayer
文档描述:
The CAReplicatorLayer class creates a specified number of copies of its sublayers (the source layer), each copy potentially having geometric, temporal and color transformations applied to it.
简介
- 支持系统:>=iOS3.0。
- 文档释义:CAReplicatorLayer类可用来从layer源高效复制多个实体对象,每个实体对象都可以拥有几何形状、颜色、时间层次上的不同转换。
- 实际应用: 加载动画、镜像layer的生成。
使用示例1:实现一个镜像反射效果
1.创建一个模板层
/* 创建一个模板层 CAReplicatorLayer会按照一定的规则“克隆”这个模板 */
CAShapeLayer *shape = [CAShapeLayer layer];
shape.frame = CGRectMake(0, 0, 80, 80);
/* 绘制模板的形状 */
shape.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 80, 80)].CGPath;
/* 模板的填充颜色 */
shape.fillColor = [UIColor redColor].CGColor;
shape.opacity = 0.0;
/* 创建所有的子层的动画组(也可以是单个动画) */
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
/* 动画组元素 */
animationGroup.animations = @[[self alphaAnimation],[self scaleAnimation]];
/* 动画执行时间 */
animationGroup.duration = 4.0;
animationGroup.autoreverses = NO;
animationGroup.repeatCount = HUGE;
/* 给模板层添加动画 实质上也是给每个CAReplicatorLayer子层添加动画 */
[shape addAnimation:animationGroup forKey:@"animationGroup"];
/* 创建CAReplicatorLayer对象 */
CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer];
replicatorLayer.frame = self.containerView.bounds;
/* 设置每个元素的添加间隔时间 */
replicatorLayer.instanceDelay = 0.5;
/* 设置每元素个数 */
replicatorLayer.instanceCount = 8;
/* 给CAReplicatorLayer对象的子层添加转换规则 这里决定了子层的布局 */
replicatorLayerY.instanceTransform = CATransform3DTranslate(CATransform3DIdentity, 0, radius+between, 0);
/* 添加子层 */
[replicatorLayer addSublayer:shape];
Note:在这里,大家可以根据需要添加不同的动画元素或者不添加任何动画,该用法多用于实现加载提示视图的动画制作。
2.实现某个视图的反射效果
我们首先继承UIView创建一个子类,在子类的+(Class)layerClass方法中设置当前视图对象的layer为CAReplicatorLayer对象:
+ (Class)layerClass{
return [CAReplicatorLayer class];
}
然后在创建该子类的对象时对self.layer进行设置相关参数:
- (void)setup{
/* 获取当前的layer 实际上为CAReplicatorLayer对象 */
CAReplicatorLayer *layer = (CAReplicatorLayer *)self.layer;
layer.instanceCount = 2;
layer.anchorPoint = CGPointMake(0.5, 0.5);
/* 创建3D转换效果 */
CATransform3D transform = CATransform3DIdentity;
CGFloat verticaloffset = self.bounds.size.height ;
transform = CATransform3DTranslate(transform, 0, verticaloffset, 0);
/* 设置Y轴镜面反射 */
transform = CATransform3DScale(transform, 1, -1, 0);
transform = CATransform3DRotate(transform, -M_PI / 4, 1, 0, 0);
layer.instanceTransform = transform;
/* 镜面的透明度 越低显示越清晰 因为是镜面效果 */
layer.instanceAlphaOffset = -0.1;
}
效果图如下:

示例2:CAReplicatorLayer作为核心技术实现加载动画。
1.首先,创建一个UIView的子类,并暴露相关方法:
@interface JHHJView : UIView
/* 显示加载动画 并添加到父视图上 */
+ (void)showLoadingOnView:(UIView *)superView Type:(JHHJViewType)type;
/* 显示动画 并添加在主窗口上 */
+ (void)showLoadingOnTheKeyWindowWithType:(JHHJViewType)type;
/* 停止动画 */
+ (void)hideLoading;
/* 设置动画背景色(全屏背景色) */
+ (void)backgroudColor:(UIColor *)color;
/* 设置中心视图的动画背景颜色 默认透明色 */
+ (void)centerBGViewBackgroudColor:(UIColor *)color;
2.并且声明了一个枚举类型:该枚举类型代表着加载动画类型。
typedef NS_ENUM(NSInteger,JHHJViewType){
/**
* 线性动画
*/
JHHJViewTypeSingleLine = 0,
/**
* 方形点动画
*/
JHHJViewTypeSquare = 1,
/**
* 三角形运动动画
*/
JHHJViewTypeTriangleTranslate = 2,
/**
* 原型视图裁剪动画
*/
JHHJViewTypeClip
};
3.在.m文件中,该类拥有的成员变量如下:
@interface JHHJView ()
//中心背景视图
@property (nonatomic,strong)JHHJCenterBGView *centerBGView;
//计时器
@property (nonatomic,strong)NSTimer * clipTimer;
//层数组
@property (nonatomic,strong)NSMutableArray * clipLayerArr;
//计时器计量数
@property (nonatomic,assign) long long currentTimerIndex;
//背景层
@property (nonatomic,strong) CAShapeLayer *bgLayer;
@end
4.然后,设置以单例的方式创建该类的对象:
/**
* 对象单例化
*
* @return 单例对象
*/
+ (JHHJView *)shareInstanceJHHJView{
static JHHJView * instance = nil;
if (!instance) {
instance = [[JHHJView alloc] initWithFrame:[UIScreen mainScreen].bounds];
instance.centerBGView = [[JHHJCenterBGView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
instance.centerBGView.center = CGPointMake(K_IOS_WIDTH / 2, K_IOS_HEIGHT/2);
[instance addSubview:instance.centerBGView];
}
return instance;
}
5.动画的实现如下:
/**
* 展示动画视图 并添加到依赖视图上
*
* @param superView 依赖的父视图
* @param type 动画样式
*/
+ (void)showLoadingOnView:(UIView *)superView Type:(JHHJViewType)type{
/* 在显示前 先从父视图移除当前动画视图 */
JHHJView *instance = [[self class] shareInstanceJHHJView];
[[self class] hideLoading];
/* 显示前 先将动画图层从中心视图上移除 */
for (CALayer *layer in instance.centerBGView.layer.sublayers) {
[layer removeFromSuperlayer];
}
/* 按照type初始化动画 */
switch (type) {
case JHHJViewTypeSingleLine:
{
CALayer *layer = [instance lineAnimation];
layer.position = CGPointMake(CGRectGetWidth(instance.centerBGView.frame)/2 - 25, CGRectGetHeight(instance.centerBGView.frame)/2);
[instance.centerBGView.layer addSublayer:layer];
}break;
case JHHJViewTypeSquare:
{
CALayer *layer = [[self class] qurareAnimation];
layer.position = CGPointMake(CGRectGetWidth(instance.centerBGView.frame)/2, CGRectGetHeight(instance.centerBGView.frame)/2);
[instance.centerBGView.layer addSublayer:layer];
}break;
case JHHJViewTypeTriangleTranslate:
{
CALayer *layer = [[self class] triangleAnimation];
layer.position = CGPointMake(CGRectGetWidth(instance.centerBGView.frame)/2 - 18, CGRectGetHeight(instance.centerBGView.frame)/2 - 15);
[instance.centerBGView.layer addSublayer:layer];
}break;
case JHHJViewTypeClip:
{
CALayer *layer = [[self class] clipAnimation];
layer.position = CGPointMake(CGRectGetWidth(instance.centerBGView.frame)/2 , CGRectGetHeight(instance.centerBGView.frame)/2 - 15);
[instance.centerBGView.layer addSublayer:layer];
}break;
default:
break;
}
[superView addSubview:instance];
}
6.下面来具体实现其中一个动画,以三角形旋转动画为例:
/**
* 三角形运动动画
*
* @return 动画实例对象
*/
+ (CALayer *)triangleAnimation{
/* 基本间距确定及模板层的创建 */
CGFloat radius = 50/4.0;
CGFloat transX = 50 - radius;
CAShapeLayer *shape = [CAShapeLayer layer];
shape.frame = CGRectMake(0, 0, radius, radius);
shape.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, radius, radius)].CGPath;
shape.strokeColor = [UIColor redColor].CGColor;
shape.fillColor = [UIColor redColor].CGColor;
shape.lineWidth = 1;
[shape addAnimation:[JHHJAnimation rotateAnimation] forKey:@"rotateAnimation"];
/* 创建克隆层 */
CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer];
replicatorLayer.frame = CGRectMake(0, 0, radius, radius);
replicatorLayer.instanceDelay = 0.0;
replicatorLayer.instanceCount = 3;
CATransform3D trans3D = CATransform3DIdentity;
trans3D = CATransform3DTranslate(trans3D, transX, 0, 0);
trans3D = CATransform3DRotate(trans3D, 120.0*M_PI/180.0, 0.0, 0.0, 1.0);
replicatorLayer.instanceTransform = trans3D;
[replicatorLayer addSublayer:shape];
return replicatorLayer;
}
流程如上,效果图如下:

项目文件截图
神奇的CAReplicatorLayer
注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权
神奇的CAReplicatorLayer的更多相关文章
- CAReplicatorLayer复制Layer和动画, 实现神奇的效果
今天我们看下CAReplicatorLayer, 官方的解释是一个高效处理复制图层的中间层.他能复制图层的所有属性,包括动画. 一样我们先看下头文件 @interface CAReplicatorLa ...
- BZOJ 1006 【HNOI2008】 神奇的国度
题目链接:神奇的国度 一篇论文题--神奇的弦图,神奇的MCS-- 感觉我没有什么需要多说的,这里简单介绍一下MCS: 我们给每个点记录一个权值,从后往前依次确定完美消除序列中的点,每次选择权值最大的一 ...
- 前端精选文摘:BFC 神奇背后的原理
BFC 已经是一个耳听熟闻的词语了,网上有许多关于 BFC 的文章,介绍了如何触发 BFC 以及 BFC 的一些用处(如清浮动,防止 margin 重叠等).虽然我知道如何利用 BFC 解决这些问题, ...
- MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)
前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...
- 一行神奇的javascript代码
写本篇文章的缘由是之前群里@墨尘发了一段js代码,如下: (!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~ ...
- [翻译svg教程]Path元素 svg中最神奇的元素!
先看一个实例 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999 ...
- php isset( $test ) 的神奇之处。
很久一段时间没更新博客了,由于近段时间一直在忙 挑战杯 的项目,所以没怎样把一些总结放上来.这次,总结下 php 的一个 函数 : boolean isset($test), 返回值:boolean类 ...
- 神奇的CSS3按钮特效
点击这里查看效果 以下是源代码: <!doctype html> <html> <!-- author: @simurai --> <head> < ...
- 吉特仓库管理系统- 斑马打印机 ZPL语言的腐朽和神奇
上一篇文章说到了.NET中的打印机,在PrintDocument类也暴露一些本质上上的问题,前面也提到过了,虽然使用PrintDcoument打印很方便.对应条码打印机比如斑马等切刀指令,不依赖打印机 ...
随机推荐
- 打印sql语句方法
var_dump($this->blackpool_model->getLastSql());
- 【转载】Linux中profile、bashrc、bash_profile之间的区别和联系
如果你想对所有的使用bash的用户修改某个配置并在以后打开的bash都生效的话可以修改这个文件,修改这个文件不用重启,重新打开一个bash即可生效.~/.bash_profile:每个用户都可使用该文 ...
- (十)while和until循环
(1)while循环 语法:当条件测试成立(真),执行循环体 while 条件测试 do 循环体 done 1)while批量创建用户1 从user.txt读取到的行数据赋予给变量user值 #!/b ...
- typescript 定义全局变量以及扩展原生js对象
使用“declare global”操作即可. 项目根目录下新建myDeclareFile.d.ts declare global { interface Navigator { mediaSessi ...
- 11.5NOIP2018提高组模拟题
书信(letter) Description 有 n 个小朋友, 编号为 1 到 n, 他们每人写了一封信, 放到了一个信箱里, 接下来每个人从中抽取一封书信. 显然, 这样一共有 n!种拿到书信的情 ...
- 洛谷——P2719 搞笑世界杯
题目背景 很久很久以后,一次世界杯,. 题目描述 随着世界杯小组赛的结束,法国,阿根廷等世界强队都纷纷被淘汰,让人心痛不已. 于是有人组织了一场搞笑世界杯,将这些被淘汰的强队重新组织起来和世界杯一同比 ...
- 利用Java的反射与代理机制实现AOP
在上一篇文章中,我们讲述了利用Java的反射机制中实现Spring中的IOC,在本文中,我们将更进一步,讲述用Java的反射和动态代理机制来实现Spring的AOP. 一.AOP概述 AOP(Aspe ...
- 【动态规划】【记忆化搜索】【dfs】bzoj2748 [HAOI2012]音量调节
f[i][j]表示第i首歌音量为j是否可能.若是将状态之间建边,那么答案就是max(j){f[i][j]==true&&0<=j<=limit}.于是就是图中dfs一遍判断 ...
- Scala实战高手****第6课 :零基础实战Scala集合操作及Spark源码解析
本课内容1.Spark中Scala集合操作鉴赏2.Scala集合操作实战 --------------------------------------------------------------- ...
- SqlMapConfig.xml详细介绍
1,连接数据库 <!--配置环境,默认的环境id为oracle --> <environments default="oracle"> <!-- 配置 ...