如何在UIImageVIew内部向后设置一组UIImage动画-Swift-以编程方式

问题描述

我有一个UIImages数组,我试图以一种特殊的方式对其进行动画处理。就像instagram飞镖功能一样。

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

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

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()
    }
}

它看起来应该像这样:

boomerang demo

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...