美文网首页动画相关iOS学习iOS学习笔记
Swift - CAReplicatorLayer的使用

Swift - CAReplicatorLayer的使用

作者: Hesse_Huang | 来源:发表于2017-02-07 18:50 被阅读108次

    CAReplicatorLayer是CoreAnimation框架中的一个容器类,它有别于普通的如CAShapeLayer的Layer,主要是用于复制其sublayers并以特定的方式排列这些sublayers,做出一些有意思的动画效果。自定义Loading动画时就经常用到CAReplicatorLayer

    环境:Swift 3.0, Xcode 8.2
    GitHub源码:https://github.com/Hesse-Huang/CAReplicatorLearning

    效果图如下:


    CAReplicatorLayer.gif

    分析:
    1.绿色圆点
    首先圆点是给到CAReplicatorLayersublayers中的,因此需要是个CALayer对象。虽然效果图中的64个点,但是不用真的做64个对象——它们是被CAReplicatorLayer复制而来的。既然是1个点那就不难了,用CAShapeLayer + UIBezierPath搞定。

    // 在viewDidLoad()中
    self.dotLayer = CAShapeLayer()
    dotLayer.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
    dotLayer.path = UIBezierPath(ovalIn: dotLayer.bounds).cgPath
    dotLayer.fillColor = #colorLiteral(red: 0.3411764801, green: 0.6235294342, blue: 0.1686274558, alpha: 1).cgColor
    

    2.CAReplicatorLayer复制这些绿色圆点
    这里就该是主角出场了。设置一下instanceCountinstanceDelayinstanceTransform即可。这里说明一下instanceTransform属性:它控制这些instance的排列方式(或者说是而布局方式),需要传入一个CATransform3D结构体。CATransform3DCGAffineTransform有点像,无非就是平移、旋转和缩放三种效果,但使用时需要用回诸如CATransform3DMakeTranslation(_:_:_:)这样的那些传统的全局函数。
    第n+1个圆点的位置是根据第n个圆点的坐标系确定的,因此如果是水平方向上平移,则是 Pn+1.x = Pn.x + xOffset。如果变换中涉及旋转,那就得要注意了,角度也是会累积的哦。

    let replicatorLayerX = CAReplicatorLayer()
    replicatorLayerX.frame = CGRect(x: 60, y: 100, width: 30, height: 30)  // 1️⃣
    replicatorLayerX.instanceCount = 8      // 实例数,这里8个
    replicatorLayerX.instanceDelay = 0.1    // 每个实例之间动画延迟
    replicatorLayerX.instanceTransform = CATransform3DMakeTranslation(32, 0, 0)     // 每个实例间的排列方式
    replicatorLayerX.addSublayer(dotLayer)
    
    view.layer.addSublayer(replicatorLayerX)  // 2️⃣
    

    Run一下,可以看到这样的效果。


    CAReplicatorLayer2.gif

    3.实现8x8矩阵
    我们再用一个CAReplicatorLayer再包装一下上面的replicatorLayerX,让它在垂直方向上排列,就实现了效果图中的实现8x8矩阵了。

    let replicatorLayerY = CAReplicatorLayer()
    replicatorLayerY.frame = CGRect(x: 60, y: 100, width: 30, height: 30)
    replicatorLayerY.instanceCount = 8
    replicatorLayerY.instanceDelay = 0.1
    replicatorLayerY.instanceTransform = CATransform3DMakeTranslation(0, 32, 0)
    replicatorLayerY.addSublayer(replicatorLayerX)
    
    view.layer.addSublayer(replicatorLayerY)
    

    记得注释掉1️⃣和2️⃣两行代码。

    最后,因为圆点有缩放和透明度变化两个动画,我们需要有这两个动画对象,用CAAnimationGroup加入到dotLayer中。

    var scaleAnimation: CABasicAnimation {
        let a = CABasicAnimation(keyPath: "transform")
        let t = CATransform3DIdentity
        a.fromValue = NSValue(caTransform3D: CATransform3DScale(t, 0.5, 0.5, 0.5))
        a.toValue = NSValue(caTransform3D: CATransform3DScale(t, 1, 1, 1))
        return a
    }
    
    var opacityAnimation: CABasicAnimation {
        let a = CABasicAnimation(keyPath: "opacity")
        a.fromValue = 1.0
        a.toValue = 0.2
        return a
    }
    
    @IBAction func startAnimation(_ sender: UIButton) {
        let ag = CAAnimationGroup()
        ag.animations = [scaleAnimation, opacityAnimation]
        ag.duration = 0.8
        ag.autoreverses = true
        ag.repeatCount = 10000
        dotLayer.add(ag, forKey: "groupAnimation")
    }
    

    最终效果请看原码哦,喜欢请点赞,交流请评论~

    相关文章

      网友评论

        本文标题:Swift - CAReplicatorLayer的使用

        本文链接:https://www.haomeiwen.com/subject/uakmittx.html