ios - 如何正确设置CABasicAnimation(开始)时间?

标签 ios delay cabasicanimation

我使用 CABasicAnimation 为存储在数组中的 CAShapeLayers 的颜色设置动画。动画根据 animation.duration 不规律地显示,我不知道为什么。我怀疑 animation.beginTime = CACurrentMediaTime() + delay

有问题

动画描述

动画包含连续闪烁的形状,一旦动画结束,它们就会变成黄色,然后变成黑色。

动画的当前状态

当动画持续时间超过一定时间时,它会正常工作。

  • 例如持续时间为 2 秒:

2-second animation

但是当我缩短持续时间时,结果会大不相同。

  • 例如,持续时间为 1 秒:

1-second animation:

您会注意到动画已经缓存/结束前 10 个左右的小节,然后等待并开始为其余形状设置动画。

  • 同样,持续时间为 0.5 秒:

0.5s animation

在这种情况下,在一定时间后显示一些动画之前,似乎有更多的动画已经结束(形状为黑色)。您还可以注意到,虽然形状颜色动画应该持续相同的持续时间 (0.5s),但有些感觉比其他动画更快。

代码

动画在 UIViewController 类的 viewDidAppear 方法中调用。

我创建了一个 UIView 自定义类来绘制我的形状,并使用该类的扩展为它们制作动画。

动画颜色的代码:

    enum ColorAnimation{
        case continuousSwap
        case continousWithNewColor(color: UIColor)
        case randomSwap
        case randomWithNewColor(color: UIColor)
        case randomFromUsedColors
    }


    func animateColors(for duration: Double,_ animationType: ColorAnimation, colorChangeDuration swapColorDuration: Double){
        guard abs(swapColorDuration) != Double.infinity else {
            print("Error in defining the shape color change duration")
            return
        }
        let animDuration = abs(duration)
        let swapDuration = abs(swapColorDuration)
        let numberOfSwaps = Int(animDuration / min(swapDuration, animDuration))


        switch animationType {
        case .continousWithNewColor(color: let value):
            var fullAnimation = [CABasicAnimation]()
            for i in (0...numberOfSwaps) {
                let index = i % (self.pLayers.count)
                let fromValue = pLayers[index].pattern.color
                let delay =  Double(i) * swapDuration / 3
                let anim = colorAnimation(for: swapDuration, fromColor: value, toColor: fromValue, startAfter: delay)
                fullAnimation.append(anim)
            }

            for i in (0...numberOfSwaps) {
                CATransaction.begin()
                 let index = i % (self.pLayers.count)
                CATransaction.setCompletionBlock {
                    self.pLayers[index].shapeLayer.fillColor = UIColor.black.cgColor
                }
                pLayers[index].shapeLayer.add(fullAnimation[i], forKey: "fillColorShape")
                CATransaction.commit()
            }
        default:
            ()
        }
    }

根据颜色变化的持续时间来分割整个动画的持续时间(例如如果整个动画是 10 秒,每个形状在 1 秒内变色,这意味着有 10 个形状会变色)。 然后,我使用方法 colorAnimation(for: fromColor, toColor, startAfter:) 创建 CABasicaAnimation 对象。

func colorAnimation(for duration: TimeInterval, fromColor: UIColor, toColor: UIColor, reverse: Bool = false, startAfter delay: TimeInterval) -> CABasicAnimation {
        let anim = CABasicAnimation(keyPath: "fillColor")
        anim.fromValue = fromColor.cgColor
        anim.toValue = toColor.cgColor
        anim.duration = duration
        anim.autoreverses = reverse
        anim.beginTime = CACurrentMediaTime() + delay
        return anim
    }

最后,我将动画添加到适当的 CAShapeLayer。 代码显然可以优化,但我选择继续执行这些步骤以尝试找出它无法正常工作的原因。

到目前为止的尝试

到目前为止,我已经尝试过:

  • 在 colorAnimation 方法中设置和不设置 animation.beginTime,包括设置和不设置 CACurrentMediaTime():如果我不设置 animation.beginTimeCACurrentMediaTime,我根本看不到任何动画。

  • 有和没有指向 animation.delegate = self:它没有改变任何东西。

  • 使用 DispatchQueue(将动画存储在全局中并在 main 中运行)并且怀疑形状没有动画。

我怀疑 beginTime 有什么地方不能正常工作,但情况可能并非如此,或者只是因为即使形状动画,形状动画持续时间似乎也有所不同,但实际上不应该。

非常感谢您查看此问题。欢迎任何想法,即使它看起来很牵强,它可以开辟解决这个问题的新方法!

最好的,

最佳答案

其实duration和swapColorDuration是有关系的

func animateColors(for duration: Double,_ animationType: ColorAnimation, colorChangeDuration swapColorDuration: Double)

当你调用它的时候,你可能需要保持这种关系

    let colorChangeDuration: TimeInterval = 0.5
    animateColors(for: colorChangeDuration * TimeInterval(pLayers.count), .continousWithNewColor(color: UIColor.black), colorChangeDuration: colorChangeDuration)

也在这里:

 let numberOfSwaps = Int(animDuration / min(swapDuration, animDuration)) - 1

这个值可能比您需要的高一点。

问题出在这个let index = i % (self.pLayers.count)

if numberOfSwaps > self.pLayers.count , 部分波段会双动画。

 let numberOfSwaps1 = Int(animDuration / min(swapDuration, animDuration))
 let numberOfSwaps = min(numberOfSwaps1, self.pLayers.count)

剩下的是

       for i in (0..<numberOfSwaps) {... }

现在如果numberOfSwaps < self.pLayers.count .还没完。

如果 numberOfSwaps 较大,则可以。

如果需要双重动画,请更改以下内容:

pLayers[index].shapeLayer.add(fullAnimation[i], forKey: nil)

pLayers[index].shapeLayer.add(fullAnimation[i], forKey: "fillColorShape" + String(i))

关于ios - 如何正确设置CABasicAnimation(开始)时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54481385/

相关文章:

ios - 尝试快速遍历结构数组时出现奇怪的语法

ios - 如何在 iOS 11 的 iPhone X 上获得黑色状态栏

javascript - switch div 函数中 JavaScript 的时间延迟

Java-向循环流添加时间延迟

php - 如何让 sleep 函数在 PHP 的 for 循环中做出适当响应

ios - 如何在CABasicAnimation启动之前防止CAShapeLayer绘制

android - 是否可以使用蓝牙连接 iOS 和 android 设备?

ios - 是否可以在 IOS 中运行谷歌地图导航而不是苹果 map

ios - 快速水平和垂直对齐图像

ios - CABasicAnimation:从左到右