同步执行多个动画的最佳方式

Best way to execute multiple animations synchronously

这将是一个 'best way to do' 类的问题。

我知道有多种制作序列动画的方法,但哪种方法更好?

假设我有 3 个动画要执行,一个接一个,所以下一个仅在前一个完成时开始。

我可以用 UIView.animate(withCompletionBlock:) 做到这一点,所以在完成部分我调用第二个,在第二个的 completionBlock 上我调用第三个。

这个特别让我思考:这是 'beautiful' 的方法吗?在另一个中使用 completionBlocks 是否存在任何已知问题?

只是一个想法。在前一个动画完成块中调用动画,可能会使代码有点像厄运金字塔,如果有类似 10 个同步动画,你不觉得吗?

另一种方法是使用 dispatch_after,我根据前一个动画的 NSTimeInterval 调用下一个动画。在这种情况下,可能会导致应用程序崩溃暂停主线程以等待下一个执行,然后再次暂停以执行第三个。

我知道的最后一种方法是我可以使用 NSTimeInterval 来调用下一个动画,但是这个有点像 dispatch_after 选项。

您认为哪种方法最好? 同步执行 3 个或更多视觉动画(等待前一个完成后开始下一个)。

我可能会在我的应用程序中经常使用它,我想以最好的方式启动它。

例子

completionBlocks 中的动画

DispatchQueue.main.async {
        UIView.animate(withDuration: 2.0, animations: { 
            view1.alpha = 1
        }, completion: { (_) in
            UIView.animate(withDuration: 5.0, animations: {
                view2.alpha = 1
            }, completion: { (_) in
                UIView.animate(withDuration: 2.0, animations: {
                    view3.alpha = 0
                }, completion: { (_) in
                    UIView.animate(withDuration: 2.0, animations: {
                        view4.alpha = 0
                    }, completion: { (_) in
                            print("all completed")
                    })
                })
            })
        })
    }

与dispatch_after:

    let anim1_duration = 2.0
    let anim2_duration = 3.0
    let anim3_duraiton = 5.0

    UIView.animate(withDuration: anim1_duration, animations: { 
        view1.alpha = 1
    }

    DispatchQueue.main.asyncAfter(deadline: DispatchTime.init(uptimeNanoseconds: UInt64(anim1_duration * Double(NSEC_PER_SEC)))) {
        UIView.animate(withDuration: anim2_duration, animations: { 
            view2.alpha = 1
        }
    }

    DispatchQueue.main.asyncAfter(deadline: DispatchTime.init(uptimeNanoseconds: UInt64((anim1_duration + anim2_duration) * Double(NSEC_PER_SEC)))) {
        UIView.animate(withDuration: anim3_duration, animations: { 
            view3.alpha = 1
        }
    }

就'better reading code'而言,考虑这两种执行动画的方式:

  1. 构建动画堆栈:more

  2. 使用 CAKeyframeAnimation 创建关键帧动画:more

这些选项避免了我喜欢的完成块。

查看 UIView 的 animate​Keyframes(with​Duration:​delay:​options:​animations:​completion:​):

class func animateKeyframes(withDuration duration: TimeInterval, 
                      delay: TimeInterval, 
                    options: UIViewKeyframeAnimationOptions = [], 
                 animations: @escaping () -> Void, 
                 completion: ((Bool) -> Void)? = nil)

对于您的具体情况,它看起来像这样:

UIView.animateKeyframes(withDuration: 20,
                        delay: 0,
                        options: [],
                        animations: {

                            UIView.addKeyframe(withRelativeStartTime: 0,
                                               relativeDuration: 0.2,
                                               animations: {
                                view1.alpha = 1
                            })

                            UIView.addKeyframe(withRelativeStartTime: 0.2,
                                               relativeDuration: 0.3,
                                               animations: {
                                view2.alpha = 1
                            })

                            UIView.addKeyframe(withRelativeStartTime: 0.5,
                                               relativeDuration: 0.1,
                                               animations: {
                                view3.alpha = 0
                            })

                            UIView.addKeyframe(withRelativeStartTime: 0.6,
                                               relativeDuration: 0.4,
                                               animations: {
                                view4.alpha = 0
                            })
},
                        completion: nil)