您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
CALayer动画实践(二):CAReplicatorLayer的用法
 
作者:付宇轩 来源:CSDN 发布于: 2015-09-11
   次浏览      
 

摘要:本文为CALayer Animation系列第二篇。在以实战的方式对CALayer动画进行了初步的介绍,详解CALayer是如何让动画灵动起来之后,作者继续以示例讲解了更多CALayer动画的知识,主要为CAReplicatorLayer的用法。

上一篇文章通过两个动画示例带大家了解和认识了CALayer动画,包括如何使用CAShapeLayer、CABasicAnimation、CAAnimationGroup等。在这篇文章中,依然会通过两个示例向大家讲解更多CALayer动画的知识。

老规矩,先让我们看看最终要实现的动画效果:

经常听音乐的人对第一个动画效果肯定有会觉得很眼熟,类似播放音乐时音频高低起伏的动画,这种动画在应用中常被用作标识正在播放音乐或广播。第二个动画依然是一个等待加载的动画,在我的印象中肯定是有应用使用过,具体的已经记不清了。下面就让我们来实现这两个动画吧。

Replicator Animation

新建一个项目,名为ReplicatorAnimation,打开Main.storyboard,添加一个UIView,颜色位置按大家喜好设定:

添加该UIView在ViewController.swift中的Outlet:

接下来我们在ViewController.swift中添加一个方法firstReplicatorAnimation(),在该方法中编写如下代码:

let replicatorLayer = CAReplicatorLayer()  
replicatorLayer.bounds =
CGRect(x: replicatorAnimationView.frame.origin.x,
y: replicatorAnimationView.frame.origin.y,
width: replicatorAnimationView.frame.size.width,
height: replicatorAnimationView.frame.size.height)
replicatorLayer.anchorPoint = CGPoint(x: 0, y: 0)
replicatorLayer.backgroundColor = UIColor.lightGrayColor().CGColor
replicatorAnimationView.layer.addSublayer(replicatorLayer)

这里出现的CAReplicatorLayer是一个新面孔,它也是CALayer的子类,正如它的名称一样,CAReplicatorLayer可以对它自己的子Layer进行复制操作。创建了CAReplicatorLayer实例后,设置了它的尺寸大小、位置、锚点位置、背景色,并且将它添加到了replicatorAnimationView的Layer中:

这里要啰嗦几句,Layer的默认锚点坐标是(0.5, 0.5),也就是Layer的中心点位置,而Layer的position又是根据锚点计算的,所以如果你设置Layer的position属性为(10, 10),就相当于设置了Layer的中心位置为(10, 10),并不是你期望的左上角位置。所以如果Layer想使用它父视图的坐标位置,就需要将锚点位置设置为(0, 0),这样一来Layer的position属性标识的就是Layer左上角的位置:

然后我们继续在firstReplicatorAnimation()方法中添加代码:

let rectangle = CALayer()  
rectangle.bounds =
CGRect(x: 0, y: 0, width: 30, height: 90)
rectangle.anchorPoint = CGPoint(x: 0, y: 0)
rectangle.position = CGPoint(x: replicatorAnimationView.frame.origin.x + 10,
y: replicatorAnimationView.frame.origin.y + 110)
rectangle.cornerRadius = 2
rectangle.backgroundColor = UIColor.whiteColor().CGColor
replicatorLayer.addSublayer(rectangle)

通过上面的代码,再次创建了一个Layer,这次使用的是CALayer,因为我们只需要一个很普通的Layer,为其设置位置、尺寸、背景色、圆角属性,然后添加在replicatorLayer中:

动画的主体之一已经绘制好了,下面我们让它动起来。在上述代码后面,接着添加如下代码:

let moveRectangle = CABasicAnimation(keyPath: "position.y")  
moveRectangle.toValue = rectangle.position.y - 70
moveRectangle.duration = 0.7
moveRectangle.autoreverses = true
moveRectangle.repeatCount = HUGE
rectangle.addAnimation(moveRectangle, forKey: nil)

首先我们创建了按Y轴移动的动画实例,然后设置了移动的目标位置,动画持续时间,重复次数设置为无限大。这里有一个属性大家可能比较陌生,那就是autoreverses,这个属性为Bool类型,设置为true时,开启自动反向执行动画,比如示例中的白色长方形的移动动画为向上移动50个像素,如过autoreverses设置为false,那么动画结束后,会根据重复次数,白色长方形重新回到初始位置,继续向上移动,如果autoreverses设置为true,则当动画结束后,白色长方形会继续向下移动至初始位置,然后再开始第二次的向上移动动画。

编译运行看看效果:

至此,大家应该也已经看出来了,这个白色的长方形就是动画中第一个上下移动的白色长方形,那么后两个如何创建呢?还需要再写两遍上面的代码吗?请大家在下面的文章中寻找答案。

在上述代码下面再添加一行代码:

replicatorLayer.instanceCount = 3  

显而易见,这是CAReplicatorLayer的能力了,这行代码的意思是将replicatorLayer的子Layer复制3份,复制Layer与原Layer的大小、位置、颜色、Layer上的动画等等所有属性都一模一样,所以这时编译运行代码我们看不到任何不同的效果,因为三个白色长方形是重合在一起的,所以我们需要设置每个白色长方形的间隔:

replicatorLayer.instanceTransform = CATransform3DMakeTranslation(40, 0, 0) 

这行代码涉及到CAReplicatorLayer的另一个属性instanceTransform,它的作用是设置每个子Layer如何变化。CATransform3DMakeTranslation这个类的含义是使Layer根据X、Y、Z轴进行平移。现在再编译运行看看效果如何:

现在三个白色长方形的运动轨迹和时刻都是一直的,这显然不是我们想要的结果,我们需要三个白色长方形有上下起伏的视觉效果,所以我们继续添加一行代码:

replicatorLayer.instanceDelay = 0.3  

instanceDelay这个属性使CAReplicatorLayer中的每个子Layer的动画起始时间逐个递增。这里我们设置为0.3秒,也就是第一个长方形先执行动画,过0.3秒后第二个开始执行动画,再过0.3秒后第三个开始执行动画。我们编译运行看看效果:

显然我们只想显示replicatorLayer区域里的内容,我们并不想看到超出它边界的内容,所以我们再添加一行代码:

replicatorLayer.masksToBounds = true  

masksToBounds是CALayer的属性,作用是将Layer视为一个遮罩,只显示遮罩区域内的内容。最后我们回到初始化replicatorLayer的地方,找到这行代码replicatorLayer.backgroundColor = UIColor.lightGrayColor().CGColor,将replicatorLayer的背景色改为无色replicatorLayer.backgroundColor = UIColor.clearColor().CGColor。再次编译运行看看最终效果:

Replicator Indicator Animation

CAReplicatorLayer的功能是很强大的,这一节将通过另一个加载动画的实例向大家介绍它的其他特性。

首先打开Main.storyboard,拖进一个新的UIView,位置颜色随大家喜好:

随后添加该UIView在ViewController.swift中的Outlet activityIndicatorView:

然后在ViewController.swift中添加一个方法activityIndicatorAnimation,和上一个动画示例一样,我们先创建一个CAReplicatorLayer:

let replicatorLayer = CAReplicatorLayer()  
replicatorLayer.bounds = CGRect(x: 0, y: 0,
width: activityIndicatorView.frame.size.width,
height: activityIndicatorView.frame.size.height)
replicatorLayer.position = CGPoint(x: activityIndicatorView.frame.size.width/2,
y: activityIndicatorView.frame.size.height/2)
replicatorLayer.backgroundColor = UIColor.lightGrayColor().CGColor
activityIndicatorView.layer.addSublayer(replicatorLayer)

上述代码和上个示例中的差不多,唯一不同的就是replicatorLayer的锚点使用的是默认值,即锚点就是中点,position属性代表亦是中点,所以将position属性设置为父视图的中点即可。这里意在让大家多多理解CALayer中anchorPoint与position属性。接下来添加如下代码:

let circle = CALayer()  
circle.bounds = CGRect(x: 0, y: 0, width: 15, height: 15)
circle.position = CGPoint(x: activityIndicatorView.frame.size.width/2,
y: activityIndicatorView.frame.size.height/2 - 55)
circle.cornerRadius = 7.5
circle.backgroundColor = UIColor.whiteColor().CGColor
replicatorLayer.addSublayer(circle)

上述代码的目的是用CALayer创建一个圆形,其实CALayer创建出的形状默认是矩形,但是把四个角的弧度设置为边宽的一半,矩形就变成了圆形。将这个圆形的位置设置在父Layer的中间靠上位置,背景色设置为白色。此时该圆形就是文章开头效果图中第二个动画里的主体了:

不过在动画中我们看到有许多个小圆形组成一个大圆,如果重复上面的代码,一个一个设置位置,那绝对是令人发指的行为,好在我们有CAReplicatorLayer帮助我们实现,下面就来看看如何使用CAReplicatorLayer复制子Layer,并让子Layer形成一个圆形。让我们接着添加如下代码:

replicatorLayer.instanceCount = 15  
let angle = CGFloat(2 * M_PI) / CGFloat(15)
replicatorLayer.instanceTransform = CATransform3DMakeRotation(angle, 0, 0, 1)

replicatorLayer.instanceTransform = CATransform3DMakeRotation(angle, 0, 0, 1)
上述的代码中,首先对子Layer,也就是白色圆形复制了15份。然后将360°除以15份,算出每一个圆形针对它前一个圆形应该偏移的角度。最后我们用到了CATransform3DMakeRotation,它同样是CATransform3D的一个结构,含义是使Layer在X、Y、Z轴根据给定的角度旋转。这样我们复制的15份圆形就会按照我们计算的角度排列,并形成一个大圆:

接下来让我们分析一下这个动画,整体看上去感觉像一颗流星拖着尾巴在不停的转圈,但细看每一个小圆点,其实是在不停的进行放大缩小的动画,只不过每个小圆点的动画对于它前一个小圆点的动画有一定的延迟。所以首先我们需要实现小圆点放大缩小的动画,在上述代码后面接着添加如下代码:

let scale = CABasicAnimation(keyPath: "transform.scale")  
scale.fromValue = 1
scale.toValue = 0.1
scale.duration = 1
scale.repeatCount = HUGE
circle.addAnimation(scale, forKey: nil)

首先创建一个按比例缩放类型的动画,设置起始比例为1,也就是当前大小。再设置希望缩放到的比例为0.1。动画持续时间为1秒,重复无限次。最后将该动画添加在小圆点中。编译运行看看效果:

目前每个小圆点是同时执行动画,我们需要设置小圆点的动画延迟时间,接着添加如下代码:

replicatorLayer.instanceDelay = 1/15  

这里为什么是1/15呢,因为整个动画的时间是由每个小圆点的动画时间决定的,这里也就是1秒,所有小圆点的延迟时间加起来要等于整个动画的持续时间,所以这里就是用1秒除以小圆点的数量15。编译运行看看效果:

从效果图中可以看到,刚开始的动画不是很自然,那是因为小圆点的初始比例是1,所以一开始会先看到小圆点,然后才会慢慢开始正常的动画。这个问题很好解决,我们让小圆点的初始比例为0.1,也就是刚开始看不到小圆点,这样就可以避免这个情况了,我们接着加一行代码:

circle.transform = CATransform3DMakeScale(0.01, 0.01, 0.01)  

同时将replicatorLayer的背景色改为无色,再次编译运行看看效果:

展现在我们眼前的是一个完美的加载动画。

总结

今天主要给大家介绍了CAReplicatorLayer的用法,大家领悟其核心功能复制、延迟后也可以尝试实现其他有趣的动画效果。下篇文章我会向大家介绍CALayer另一个子类的用法,敬请期待吧。

   
次浏览       
 
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
 
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试
最新活动计划
LLM大模型应用与项目构建 12-26[特惠]
QT应用开发 11-21[线上]
C++高级编程 11-27[北京]
业务建模&领域驱动设计 11-15[北京]
用户研究与用户建模 11-21[北京]
SysML和EA进行系统设计建模 11-28[北京]

android人机界面指南
Android手机开发(一)
Android手机开发(二)
Android手机开发(三)
Android手机开发(四)
iPhone消息推送机制实现探讨
手机软件测试用例设计实践
手机客户端UI测试分析
手机软件自动化测试研究报告
更多...   


Android高级移动应用程序
Android应用开发
Android系统开发
手机软件测试
嵌入式软件测试
Android软、硬、云整合


领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...