代码之家  ›  专栏  ›  技术社区  ›  Antzi

UIView关键帧动画计时不符合预期

  •  1
  • Antzi  · 技术社区  · 5 年前

    我有一些动画(可在操场上测试):

    import UIKit
    import XCPlayground
    import PlaygroundSupport
    PlaygroundPage.current.needsIndefiniteExecution
    
    
    let view = UIView()
    view.frame = .init(x: 0, y: 0, width: 150, height: 150)
    view.backgroundColor = .orange
    let hand = UIView()
    view.addSubview(hand)
    hand.frame = .init(x: 0, y: 0, width: 10, height: 10)
    hand.center = view.center
    hand.backgroundColor = .green
    PlaygroundPage.current.liveView = view
    
    let fadeDuration: TimeInterval = 0.4
    let translationDuration: TimeInterval = 1
    let resetDuration: TimeInterval = 0.25
    let duration: TimeInterval =
        7 * fadeDuration +
        4 * translationDuration +
        3 * resetDuration
    var currentTime: TimeInterval  = 0.0
    
    func addKey(_ animations: @escaping () -> Void, animationTime: TimeInterval) {
        UIView.addKeyframe(withRelativeStartTime: currentTime / duration, relativeDuration: animationTime / duration, animations: animations)
        currentTime += animationTime
    }
    
    func fadeIn() {
        addKey({
            hand.alpha = 1
        }, animationTime: fadeDuration)
    }
    
    func fadeOut() {
        addKey({
            hand.alpha = 0
        }, animationTime: fadeDuration)
    }
    
    func translate(_ direction: (CGFloat) -> CGFloat) {
        let x = direction(50)
        addKey({
            hand.transform = .init(translationX: x, y: 0)
        }, animationTime: translationDuration)
    }
    
    func reset() {
        addKey({
            hand.transform = .identity
        }, animationTime: 0)
        currentTime += resetDuration
    }
    
    UIView.animateKeyframes(withDuration: duration, delay: 0, options:  .calculationModeLinear) {
        translate(-)
        fadeOut()
        reset()
        fadeIn()
        translate(-)
        fadeOut()
        reset()
        fadeIn()
        translate(+)
        fadeOut()
        reset()
        fadeIn()
        translate(+)
        fadeOut()
    } completion: { _ in
        PlaygroundPage.current.finishExecution()
    }
    

    我希望每一个 translate() 动画以相同的速度运行,但是由于某些原因,第一个和最后一个动画特别慢,尽管使用了 .calculationModeLinear

    如何做到 translationDuration duration 时间是恒定的吗?

    1 回复  |  直到 5 年前
        1
  •  0
  •   matt    5 年前

    calculationModeLinear 不同于 curveLinear . 听起来你想要后者。您正在使用 curveEaseInOut

    let animationOptions: UIView.AnimationOptions = .curveLinear
    let keyframeAnimationOptions = UIView.KeyframeAnimationOptions(rawValue: animationOptions.rawValue)
    UIView.animateKeyframes(withDuration: duration, delay: 0.1, options:  keyframeAnimationOptions) {