如何使用SwiftUI对一系列图像进行动画处理?

时间:2019-06-23 09:44:16

标签: ios swift xcode animation swiftui

如何使用SwiftUI框架对一系列图像进行动画处理(比如说Frame-1.png一直到Frame-6)?

我尝试创建“图像”数组。然后,我将UIImage.animatedImage(with:images,duration:1.0)方法分配给一个名为“ animatedImage”的变量 最后我尝试在“ ContentView.swift”的“ body”中尝试Image(uiImage:animationImage)


var images: [UIImage]! = [UIImage(named: "Sequence/frame-1")!,
                          UIImage(named: "Sequence/frame-2")!,
                          UIImage(named: "Sequence/frame-3")!,
                          UIImage(named: "Sequence/frame-4")!,
                          UIImage(named: "Sequence/frame-5")!,
                          UIImage(named: "Sequence/frame-6")!
]

let animatedImage : UIImage! = UIImage.animatedImage(with: images, duration: 1.0)

//////Then in the ContentView.swift I've tried this code:

struct ContentView : View {
    var body: some View {

        Image(uiImage: animatedImage)

    }
}

当我运行程序时,它只显示了第一帧,但是我希望这些帧有动画效果

5 个答案:

答案 0 :(得分:3)

被接受的答案非常有效,因为bhagyash ingale提到了不幸的问题,这使它很难使用。如果Image的特定方法可以通过协议或其他方法重用,将很有用。为此,我有一架非常笨拙的加农炮,想办法解决问题,但也许现在比较容易,但是现在...

class LoadingTimer {

    let publisher = Timer.publish(every: 0.1, on: .main, in: .default)
    private var timerCancellable: Cancellable?

    func start() {
        self.timerCancellable = publisher.connect()
    }

    func cancel() {
        self.timerCancellable?.cancel()
    }
}
struct LoadingView: View {

    @State private var index = 0

    private let images = (0...7).map { UIImage(named: "Image-\($0).jpg")! }
    private var timer = LoadingTimer()

    var body: some View {

        return Image(uiImage: images[index])
            .resizable()
            .frame(width: 100, height: 100, alignment: .center)
            .onReceive(
                timer.publisher,
                perform: { _ in
                    self.index = self.index + 1
                    if self.index >= 7 { self.index = 0 }
                }
            )
            .onAppear { self.timer.start() }
            .onDisappear { self.timer.cancel() }
    }
}

我不喜欢这样,但是它可以完成工作并依靠Image

答案 1 :(得分:2)

没有合并的版本

import SwiftUI

struct AnimatingImage: View {
    let images: [Image]

    @ObservedObject private var counter = Counter(interval: 0.05)
        
    var body: some View {
        images[counter.value % images.count]
    }
}

private class Counter: ObservableObject {
    private var timer: Timer?

    @Published var value: Int = 0
    
    init(interval: Double) {
        timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { _ in self.value += 1 }
    }
}

您可以使用它

struct LoadingView: View {
    private let images = (1...20).map { String(format: "i_%02d", $0) }.map { Image($0) }
    
    var body: some View {
        AnimatingImage(images: images)
    }
}

答案 2 :(得分:1)

您是否尝试过制作自己的视图包装器?

类似这样的东西:

struct AnimatedImage: UIViewRepresentable {
    func makeUIView(context: Self.Context) -> UIImageView {
        return UIImageView(image: animatedImage)
    }

    func updateUIView(_ uiView: UIImageView, context: UIViewRepresentableContext<AnimatedImage>) {
    }
}

用法是:

struct ContentView : View {
    var body: some View {
        AnimatedImage()
    }
}

不确定这是否可以解决您的问题,至少它不再是静态图像了:D

在Xcode Beta 2模拟器上进行了尝试。

答案 3 :(得分:0)

以上方法使图像具有动画效果,但是我无法应用可调整大小的修改器或设置帧大小。在我的情况下,图像太大,无法控制尺寸。

此外,我想知道如何从SwiftUI视图控制此动画。我的意思是持续时间,曲线,重复等。

最好,会很有帮助。

答案 4 :(得分:0)

我有三个要按顺序和重复命名的动画图像资产:thinking1、thinking2 和 thinking3。根据 nightwill 的回答,这适用于 iOS 14.4

// images[counter.value % images.count] mod ensures counter never exceeds images.count

import SwiftUI

struct ThinkingView: View {
    
    let images: [Image] = (1...3).map { String(format: "thinking%01d", $0) }.map { Image($0) }
    
    @ObservedObject private var counter = Counter(interval: 0.1)
    
    var body: some View {
        images[counter.value % images.count]
    }
}

private class Counter: ObservableObject {
    private var timer: Timer?

    @Published var value: Int = 0
    
    init(interval: Double) {
        timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { _ in self.value += 1 }
    }
}

struct ThinkingView_Previews: PreviewProvider {
    static var previews: some View {
        ThinkingView()
    }
}