如何在 UIImageVIew 中向后设置一组 UIImages 的动画 - swift - 以编程方式

How do I animate a set of UIImages backward inside UIImageVIew - swift - programmatically

我有一个 UIImages 数组,我正在尝试以特定方式对其进行动画处理。就像 instagram 的 boomerang 功能一样。

当动画到达最后一帧时它向后移动并到达第一帧并继续该过程。

到目前为止我一直在做的是:

imageView.animationImages = [myImages]
imageView.animationDuration = 0.9
imageView.animationRepeatCount = 2
imageView.image = imageView.animationImages?.first
imageView.startAnimating()

如果可能,我怎样才能实现回旋镖循环?

我建议我们覆盖 startAnimating() 方法。这样我们就可以提供自己的动画逻辑并决定下一帧应该是什么。

我们将创建一个 frameTimer,它将在 animationDuration 的每个相等部分替换 UIImageView 的图像。它将向前和向后遍历图像数组,直到使用 stopAnimating() 方法停止。

class BoomerangImageView: UIImageView {
    // MARK: Overrides
    override func startAnimating() {
        guard let frames = animationImages, frames.count > 1 else {
            return
        }
        image = frames.first
        
        let timePerFrame = animationDuration / Double(frames.count)
        let timer = Timer(fire: Date(timeIntervalSinceNow: timePerFrame),
                          interval: timePerFrame,
                          repeats: true) { [weak self] _ in
            self?.changeFrame()
        }
        RunLoop.current.add(timer, forMode: .common)
        frameTimer = timer
    }
    
    override func stopAnimating() {
        frameTimer?.invalidate()
        frameTimer = nil
        currentFrameIndex = 0
    }
    
    // MARK: Private
    private var frameTimer: Timer?
    private var isAnimatingForward = true
    
    private var currentFrameIndex = 0 {
        didSet {
            if let frames = animationImages,
               currentFrameIndex >= 0,
               currentFrameIndex < frames.count {
                image = frames[currentFrameIndex]
            }
        }
    }
    
    private func changeFrame() {
        guard let frames = animationImages, frames.count > 1 else {
            stopAnimating()
            return
        }
        
        let canAnimateForward = currentFrameIndex < frames.count - 1
        let canAnimateBackward = currentFrameIndex > 0
        isAnimatingForward = (isAnimatingForward && canAnimateForward) || (!isAnimatingForward && !canAnimateBackward)
        currentFrameIndex += isAnimatingForward ? 1 : -1
    }
}

然后在你的视图控制器中,你 运行 动画就像你计划的那样:

class ViewController: UIViewController {
    @IBOutlet weak var imageView: BoomerangImageView!
    
    let frames: [UIImage] = [
        // your images here
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        imageView.animationImages = frames
        imageView.animationDuration = 2
        imageView.startAnimating()
    }
}

它应该看起来像这样: