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

时间:2019-02-01 14:20:50

标签: 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:
            ()
        }
    }

将动画的整个持续时间除以颜色变化的持续时间(例如),如果整个动画为10s,每个形状的颜色更改为1s,则表示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.beginTime:如果我不使用CACurrentMediaTime设置animation.delegate = self,我根本看不到任何动画。

  • 有和没有指向body { margin: 40px; } .sidebar { grid-area: sidebar; } .content { grid-area: content; } .header { grid-area: header; display: flex; } .header div { display: flex; flex-direction: column; padding: 10px; } .footer { grid-area: footer; } .wrapper { display: grid; grid-gap: 10px; grid-template-columns: 50% 50%; grid-template-areas: "sidebar header" "sidebar content" "sidebar footer"; background-color: #fff; color: #444; } .box { background-color: #444; color: #fff; border-radius: 5px; padding: 10px; font-size: 150%; } .header, .footer { background-color: #999; }的地方:它没有任何改变。

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

我怀疑beginTime不能正常工作,但事实并非如此,或者仅仅是因为形状动画,形状动画的持续时间似乎有所变化,而它本来就不会。

非常感谢您对此问题的了解。任何想法都是欢迎的,即使它看起来牵强,也可以为解决这个问题提供新的方法!

最好

1 个答案:

答案 0 :(得分:1)

实际上,持续时间和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))