Ios 马赛克灯光显示CAReplicatorLayer动画

Ios 马赛克灯光显示CAReplicatorLayer动画,ios,swift,careplicatorlayer,Ios,Swift,Careplicatorlayer,我正在尝试使用CareReplicatorLayer对象为我的背景视图实现马赛克灯光显示效果: 每个磁贴/CALayer都是一个单独的图像,可以水平和垂直复制。那部分我已经做了 在我看来,这项任务至少分为4个部分: 随机挑选一块瓷砖 为选定的平铺选择颜色偏移的随机范围 在指定的持续时间内应用该颜色偏移(以秒为单位) 如果随机颜色偏移超过特定阈值,则在颜色偏移动画中应用辉光效果 但我不确定这是否是正确的算法 我当前的代码取自本教程: 动画不是我的强项&我实际上不知道如何在所有瓷砖上应用连续/

我正在尝试使用CareReplicatorLayer对象为我的背景视图实现马赛克灯光显示效果:

每个磁贴/CALayer都是一个单独的图像,可以水平和垂直复制。那部分我已经做了

在我看来,这项任务至少分为4个部分:

  • 随机挑选一块瓷砖
  • 为选定的平铺选择颜色偏移的随机范围
  • 在指定的持续时间内应用该颜色偏移(以秒为单位)
  • 如果随机颜色偏移超过特定阈值,则在颜色偏移动画中应用辉光效果
  • 但我不确定这是否是正确的算法

    我当前的代码取自本教程:

    动画不是我的强项&我实际上不知道如何在所有瓷砖上应用连续/重复动画。这是我目前的代码:

        @IBOutlet var animationView: UIView!
    
        func cleanUpAnimationView() {
            self.animationView.layer.removeAllAnimations()
            self.animationView.layer.sublayers?.removeAll()
        }
    
        /// Start a background animation with a replicated pattern image in tiled formation.
        func setupAnimationView(withPatternImage patternImage: UIImage, animate: Bool = true) {
            // Tutorial: https://www.swiftbysundell.com/articles/ca-gems-using-replicator-layers-in-swift/
    
            let imageSize = patternImage.size.halve
    
            self.cleanUpAnimationView()
    
            // Animate pattern image
            let replicatorLayer = CAReplicatorLayer()
            replicatorLayer.frame.size = self.animationView.frame.size
            replicatorLayer.masksToBounds = true
            self.animationView.layer.addSublayer(replicatorLayer)
    
            // Give the replicator layer a sublayer to replicate
            let imageLayer = CALayer()
            imageLayer.contents = patternImage.cgImage
            imageLayer.frame.size = imageSize
            replicatorLayer.addSublayer(imageLayer)
    
            // Tell the replicator layer how many copies (or instances) of the image needs to be rendered. But we won't see more than one since they are, per default, all rendered/stacked on top of each other.
            let instanceCount = self.animationView.frame.width / imageSize.width
            replicatorLayer.instanceCount = Int(ceil(instanceCount))
            // Instance offsets & transforms is needed to move them
            // 'CATransform3D' transform will be used on each instance: shifts them to the right & reduces the red & green color component of each instance's tint color.
    
            // Shift each instance by the width of the image
            replicatorLayer.instanceTransform = CATransform3DMakeTranslation(imageSize.width, 0, 0)
    
            // Reduce the red & green color component of each instance, effectively making each copy more & more blue while horizontally repeating the gradient pattern
            let colorOffset = -1 / Float(replicatorLayer.instanceCount)
            replicatorLayer.instanceRedOffset = colorOffset
            replicatorLayer.instanceGreenOffset = colorOffset
            //replicatorLayer.instanceBlueOffset = colorOffset
            //replicatorLayer.instanceColor = UIColor.random.cgColor
    
            // Extend the original pattern to also repeat vertically using another tint color gradient
            let verticalReplicatorLayer = CAReplicatorLayer()
            verticalReplicatorLayer.frame.size = self.animationView.frame.size
            verticalReplicatorLayer.masksToBounds = true
            verticalReplicatorLayer.instanceBlueOffset = colorOffset
            self.animationView.layer.addSublayer(verticalReplicatorLayer)
    
            let verticalInstanceCount = self.animationView.frame.height / imageSize.height
            verticalReplicatorLayer.instanceCount = Int(ceil(verticalInstanceCount))
    
            verticalReplicatorLayer.instanceTransform = CATransform3DMakeTranslation(0, imageSize.height, 0)
            verticalReplicatorLayer.addSublayer(replicatorLayer)
    
            guard animate else { return }
    
            // Set both the horizontal & vertical replicators to add a slight delay to all animations applied to the layer they're replicating
            let delay = TimeInterval(0.1)
            replicatorLayer.instanceDelay = delay
            verticalReplicatorLayer.instanceDelay = delay
    
            // This will make the image layer change color
            let animColor = CABasicAnimation(keyPath: "instanceRedOffset")
            animColor.duration = animationDuration
            animColor.fromValue = verticalReplicatorLayer.instanceRedOffset
            animColor.toValue = -1 / Float(Int.random(replicatorLayer.instanceCount-1))
            animColor.autoreverses = true
            animColor.repeatCount = .infinity
            replicatorLayer.add(animColor, forKey: "colorshift")
    
            let animColor1 = CABasicAnimation(keyPath: "instanceGreenOffset")
            animColor1.duration = animationDuration
            animColor1.fromValue = verticalReplicatorLayer.instanceGreenOffset
            animColor1.toValue = -1 / Float(Int.random(replicatorLayer.instanceCount-1))
            animColor1.autoreverses = true
            animColor1.repeatCount = .infinity
            replicatorLayer.add(animColor1, forKey: "colorshift1")
    
            let animColor2 = CABasicAnimation(keyPath: "instanceBlueOffset")
            animColor2.duration = animationDuration
            animColor2.fromValue = verticalReplicatorLayer.instanceBlueOffset
            animColor2.toValue = -1 / Float(Int.random(replicatorLayer.instanceCount-1))
            animColor2.autoreverses = true
            animColor2.repeatCount = .infinity
            replicatorLayer.add(animColor2, forKey: "colorshift2")
        }
    

    两者都产生了错误


    我删除了
    halve
    并注释掉
    animColor
    行,代码运行并设置动画。在使用您的代码之前,我无法让任何replicator层显示或设置动画(即使是最基本的apple或教程代码)。非常感谢你

    啊,是的,“减半”是CGSize的一个方便的var扩展,它只将大小减半动物颜色“。。。我不记得这是怎么回事,但这是一种关于颜色的自定义逻辑。很高兴有人从中得到了有用的东西:)
     let imageSize = patternImage.size.halve 
    
     animColor.toValue = -1 / Float(Int.random(replicatorLayer.instanceCount-1))