Swift每日一练:妙用CAReplicationLayer

今天我们来学习一下一个在iOS常常被忽视的类 - CAReplicationLayer。我们要使用这个类来完成两个开起来很炫酷的加载效果。

老样子,先上具体的效果一看

怎么样,效果还不错吧。一个是看起来有渐变效果的圆形加载,另外一个则是模仿Apple Music的柱状图加载。

接下来,就让我们一起揭开实现的面纱吧!

CAReplicationLayer

CAReplicationLayer是CALayer的子类,它与传统的CALayer系列不同,它基本不直接承担诸多效果,而是更多的承担一种“容器”的职责。

怎么理解呢?大家可以把CAReplicationLayer看成一个工厂,你提供给他一个产品的模型,它就可以为了源源不断的复制出纺织品。回到iOS中来说就是,你提供一个CALayer给CAReplicationLayer,并告诉它你希望它复制几份,就打造出多个具有效果样式的Layer。不仅如此,动画效果也会被一同复制

因此,对于CAReplicationLayer,我们有几个特别需要关注的参数。

  • instanceCount: 代表你希望将你提供它的Layer复制几份
  • instanceDelay: 这个参数在编写动画的前提下特别有用,它表明对每一个复制(或者原生)出来的Layer,启动动画之间的时间差在多少。
  • instanceTransform: 这个参数表示对于每一个Layer,它们之间的形变差距是多少。比如,每个Layer需要有相同的间隔。

渐变效果的圆形加载

了解完CAReplicationLayer的基本知识以后,我们首先来看看圆形加载效果怎么实现。

第一步,毫无疑问的,需要构建一个CAReplicationLayer。

let replicationLayer2 = CAReplicatorLayer()

第二部,需要一个样品,让我们的CAReplicationLayer复制生产

let circle = CAShapeLayer()
circle.path = UIBezierPath(ovalInRect: CGRect(x: 0, y: 0, width: 10, height: 10)).CGPath
circle.lineWidth = 1
circle.fillColor = UIColor.whiteColor().CGColor
circle.transform = CATransform3DMakeScale(0.1, 0.1, 0.1)

在这里,我们构建了一个白色小球,把初始大小设置为了0.1。

接下去,我们需要然CAReplicationLayer开始复制了,

replicationLayer2.instanceCount = 12
replicationLayer2.instanceTransform = CATransform3DMakeRotation(CGFloat(2 * M_PI/12.0), 0.0, 0.0, 1.0)

从上述代码我们可以看出,我们首先构建了12个复制体,然后将这12个小球通过instanceTransform绕Z轴均匀的分度在圆周上。

现在赶快run一下你的app,看看效果是不是正如我所说的!

现在万事具备,只欠动画了!

首先我们来定义如例子中的放缩动画

func scaleAnimation() -> CABasicAnimation {
    let animation = CABasicAnimation(keyPath: "transform.scale")
    animation.duration = 1.5
    animation.fromValue = 1.0
    animation.toValue = 0.1
    animation.repeatCount = Float.infinity

    return animation
}

我们定义了一个针对scale属性、时常1.5s的动画,然后我们将这个动画添加到小球上。

circle.addAnimation(scaleAnimation(), forKey: "scale")

现在如果你跑一下代码的话,你会发现,所有的小球都同时启动了动画,和例子的效果不一致,怎么回事呢?

嘿嘿,还记得我们之前提及的属性instanceDelay吗?没错,我们需要借助它的力量。

replicationLayer2.instanceDelay = 1.5/12

现在再看看?哈哈,效果拔群!

Apple Music加载效果

下面的代码,很清晰易懂,我就不逐条解析啦,有问题欢迎大家在下方评论!

// 1. 创建容器ReplicationLayer
let replicationLayer = CAReplicatorLayer()

// 2. 创建柱状图
let bar = CALayer()
bar.frame = CGRect(x: 0, y: 0, width: 8, height: 40)
bar.position = CGPoint(x: 10, y: 75)
bar.backgroundColor = UIColor.purpleColor().CGColor

// 3. 复制生产3个,并添加水平间隔
replicationLayer.addSublayer(bar)
replicationLayer.instanceCount = 3
replicationLayer.instanceTransform = CATransform3DMakeTranslation(20, 0, 0)

// 4. 创建动画,构造时间差
func jumpAnimation(bar:CALayer) -> CABasicAnimation {
    let animation = CABasicAnimation(keyPath: "position.y")
    animation.toValue = bar.position.y - 35.0
    animation.duration = 0.45
    animation.autoreverses = true
    animation.repeatCount = Float.infinity

    return animation
}

bar.addAnimation(jumpAnimation(bar), forKey: "jump")
replicationLayer.instanceDelay = 0.3