Swift:重复的连续 CABasicAnimations

Swift: consecutive CABasicAnimations that repeat

目标:

我的代码:

let animation = CABasicAnimation(keyPath: "transform.scale")
        animation.fromValue = 1.0
        animation.toValue = 1.5
        animation.duration = 1.0
        animation.autoreverses = true
        animation.repeatCount = .greatestFiniteMagnitude
        image1.layer.add(animation, forKey: animation.keyPath)

        let animation2 = CABasicAnimation(keyPath: "transform.scale")
        animation2.fromValue = 1.0
        animation2.toValue = 2.0
        animation2.duration = 1.0
        animation2.fillMode = .forwards

        let animation2b = CABasicAnimation(keyPath: "opacity")
        animation2b.fromValue = 1.0
        animation2b.toValue = 0.0
        animation2b.duration = 1.0
        animation2b.fillMode = .forwards

        let animationGroup = CAAnimationGroup()
        animationGroup.animations = [animation2, animation2b]
        animationGroup.duration = 2.0
        animationGroup.beginTime = 1.0
        animationGroup.repeatCount = .greatestFiniteMagnitude
        image2.layer.add(animationGroup, forKey: "scaleAndFade")

目标是在第一个动画之后开始第二个动画 1.0。由于动画组的持续时间为 2.0,而其中的动画只有 1.0,因此动画将从 1.0 开始,以 2.0 结束,然后直到 3.0

才再次重复

这两个动画有时会匹配,但并非在每个版本上都匹配。是否有更可靠的方法来启动第二个动画以恰好在初始动画的第一个完成动画结束时开始?这样他们就会从那时起保持同步。感谢您的帮助!

我不太清楚我们要实现的目标,但我的感觉是我们有两个视图,其中包含需要协调的重复动画。为了演示如何完成此操作的示例,我选择将两个动画都先放大再缩小:

这里的gif动画在重复几次后就结束了,但实际上一直在重复。

简单实现如下:

func step1() {
    UIView.animate(withDuration: 1, animations: {
        self.v1.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
        self.v2.transform = .identity
    }) { _ in
        DispatchQueue.main.async {
            self.step2()
        }
    }
}

func step2() {
    UIView.animate(withDuration: 1, animations: {
        self.v1.transform = .identity
        self.v2.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
    }) { _ in
        DispatchQueue.main.async {
            self.step1()
        }
    }
}

重点是动画的各个阶段永远不会在两个视图之间不同步,因为每个阶段都涉及两个个视图和后续 前一阶段。所以我很确定你可以调整这种方法来适应你的动画。

我喜欢@matt 的回答并且总是感谢他们的意见,但是由于我尝试使用 CAAnimation(特别是我想使用 CAKeyframeAnimation),我最终使用 CATransaction.begin()CATransaction.setCompletionBlock 嵌套了两个 CATransactions恰好在另一个动画结束时开始一个动画,然后递归地重复调用该函数。

CATransaction documentation