这里主要介绍使用 container layer 实现 replicate animations。
创建一个形状,一个图像或者任何可以用图层绘制的东西, CAReplicatorLayer 可以在屏幕上复制它。效果如下:

CAReplicatorLayer 的强悍在于: 你可以很容易地指导它使每个克隆体与它稍有不同。
例如,我们可以逐步更改每个副本的颜色。我们的原始层可以是洋红色的,当我们创建每个副本时,其颜色将向青色渐变。

此外,我们还可以在副本之间进行转换。例如,我们可以在每个副本之间应用一个简单的旋转变换,将它们绘制成一个圆圈,如图所示:

但是更强大的功能是我们可以为每个拷贝层进行动画延迟。当我们将一个instanceDelay 设为 0.2 秒,并在原始 layer 中添加一个动画时,第一个拷贝 layer 将延迟 0.2 秒动画,第二个拷贝 layer 将延迟 0.4 秒动画,第三个拷贝 layer 延迟 0.6 秒动画,以此类推。
我们可以同时添加多个动画特效来创建引人入胜的复杂动画。
复制多个动画
Scale animation
let scale = CABasicAnimation(keyPath: "transform")
scale.fromValue = NSValue(caTransform3D: CATransform3DIdentity)
scale.toValue = NSValue(caTransform3D:CATransform3DMakeScale(1.4, 15, 1.0))
scale.duration = 0.33
scale.repeatCount = .infinity
scale.autoreverses = true
scale.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseOut)
dot.add(scale, forKey: "dotScale")

其中 CATransform3D 的数据结构定义了一个同质的三维变换(4x4 CGFloat值的矩阵),用于图层的旋转,缩放,偏移,歪斜和应用的透视。
CATransform3DIdentity 是单位矩阵,该矩阵没有缩放,旋转,歪斜,透视。该矩阵应用到图层上,就是设置默认值。
变换函数 CATransform3DMakeTranslation:
对于CATransform3D来说,它是一个4x4 CGFloat的矩阵:[1 0 0 0; 0 1 0 0; 0 0 1 0; tx ty tz 1]。
给竖起来后。就发现:
1 0 0 0
0 1 0 0
0 0 1 0
tx ty tz 1
CATransform3D 是一个结构。他有自己的一个公式,可以进行套用。
struct CATransform3D
{
CGFloat m11(x缩放), m12(y切变),m13(旋转), m14();
CGFloat m21(x切变), m22(y缩放),m23() , m24();
CGFloat m31(旋转) , m32( ), m33() , m34(透视);
CGFloat m41(x平移), m42(y平移),m43(z平移), m44();
};
m34(透视效果,要操作的这个对象要有旋转的角度,否则没有效果。正直/负值都有意义)
CATransform3D CATransform3DMakeScale (CGFloat sx, CGFloat sy, CGFloat sz);
sx:X轴缩放,代表一个缩放比例,一般都是 0 -- 1 之间的数字。
sy:Y轴缩放。
sz:整体比例变换时,也就是 m11(sx)== m22(sy)时,若 m33(sz)>1,图形整体缩小,若 sz <1,图形整体放大,若 m33(sz)<0,发生关于原点的对称等比变换。
Opacity animation
将 dot layer 淡入、淡出,将使波具有一定的维数,并随着波的增大和减小而改变 alpha 的值,以模拟光的情况。它看起来就像一个旋转的弯曲的丝带糖果:

实现代码如下:
let fade = CABasicAnimation(keyPath: "opacity")
fade.fromValue = 1.0
fade.toValue = 0.2
fade.duration = 0.33
fade.beginTime = CACurrentMediaTime() + 0.33
fade.repeatCount = .infinity
fade.autoreverses = true
fade.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseOut)
dot.add(fade, forKey: "dotOpacity")
在缩放动画的持续时间内,将 dot layer 的 opacity 从 1.0 降低到 0.2 。这一次,开始动画的延迟是 0.33 秒。当波浪达到最大时,就会开始消退效应。

Tint animation
有了波浪形动画,给它们上色成彩色是不是更好呢?
加色彩很简单,如下:
let tint = CABasicAnimation(keyPath: "backgroundColor")
tint.fromValue = UIColor.magenta.cgColor
tint.toValue = UIColor.cyan.cgColor
tint.duration = 0.66
tint.beginTime = CACurrentMediaTime() + 0.28
// kCAFillModeRemoved – 此为默认值,layer在动画前的属性值一直为origin value,动画开始时属性值立马切换到from value,然后动画变化到to value,动画结束时属性值又立马切换到origin value;
// kCAFillModeForwards – layer在动画结束时仍然保持属性值为to value;
// kCAFillModeBackwards – layer在动画前就将属性值切换到origin value;
tint.fillMode = kCAFillModeBackwards
tint.repeatCount = .infinity
tint.autoreverses = true
tint.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut) dot.add(tint, forKey: "dotColor")
这个动画改变 dot layer 的颜色从洋红色到青色再到洋红色,如此循环。动画持续时间 0.66 秒,这是缩放动画频率的两倍。
我们还给动画延迟了 0.28 秒,这使得色彩色调动画在波形出现 “扭曲” 之前就开始了。 这种微妙的效果在波浪 “扭曲” 之前提供了下一种颜色的暗示,好像有一些反射正在进行。

Animating CAReplicatorLayer properties
我们可以为 CAReplicatorLayer 的基本属性(如position,backgroundColor或cornerRadius)设置动画,可以通过设置此图层中存在,其它图层中不存在的某些特殊属性来创建一些有趣的效果。
CAReplicatorLayer 可动画的属性有:
• instanceDelay: 动画实例之间的延迟量
• instanceTransform: 进行 3D 变换
• instanceColor: 更改用于所有实例的混合颜色
• instanceRedOffset, instanceGreenOffset, instanceBlueOffset: 实例颜色组件的应用增量
• instanceAlphaOffset: 实例的不透明度增量
为语音波浪添加特效
let initialRotation = CABasicAnimation(keyPath:"instanceTransform.rotation")
initialRotation.fromValue = 0.0
initialRotation.toValue = 0.01
initialRotation.duration = 0.33
initialRotation.isRemovedOnCompletion = false
initialRotation.fillMode = kCAFillModeForwards
initialRotation.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseOut)
replicator.add(initialRotation, forKey: "initialRotation")
将实例之间的旋转设置为 0.0 弧度到 0.01 弧度。 与其邻居相比,每个复制 layer 都会略微旋转。

继续添加动画:
let rotation = CABasicAnimation(keyPath: "instanceTransform.rotation") rotation.fromValue = 0.01
rotation.toValue = -0.01
rotation.duration = 0.99
rotation.beginTime = CACurrentMediaTime() + 0.33
rotation.repeatCount = .infinity
rotation.autoreverses = true
rotation.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut) replicator.add(rotation, forKey: "replicatorRotation")
这里,在 instanceTransform.rotation 上运行第二个动画,该动画在第一个动画完成后启动,它将变换旋转从 0.01 弧度(第一个动画的最终值)设置为 -0.01 弧度,然后自动反循环。

参考:
网友评论