xcode 如何使用SwiftUI动画一系列图像?

o4tp2gmn  于 2023-08-07  发布在  Swift
关注(0)|答案(4)|浏览(155)

我如何使用SwiftUI框架来制作一系列图像的动画(比如从Frame-1.png到Frame-6)?
我尝试创建一个“图像”数组。然后我分配了UIImage.animatedImage(with:图像,持续时间:1.0)方法调用一个名为“animatedImage”的变量,最后我尝试了Image(uiImage:animatedImage)在“ContentView.swift”的“body”中

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)

    }
}

字符串
当我运行程序时,它只显示第一帧,但我希望帧的动画

yebdmbv4

yebdmbv41#

公认的答案工作得很好,与不幸的问题提到的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()
    }
}

个字符
我不喜欢这样,但它可以完成工作,并依赖于Image

aiazj4mn

aiazj4mn2#

未合并的版本

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

wmtdaxz3

wmtdaxz33#

我从image array中找到了一个纯SwftUI动画:它使用一个可设置动画的修改器来处理要显示的图像,而不是视图(这里是一个带有图像的按钮)。当你点击一个按钮时,它的图像会显示动画。如果您再次点击图像停止动画并显示默认按钮图像:

//
//  ImageArrayAnimationView
//
//  Created by Pitt Xav
//
import SwiftUI

struct ImageArrayAnimationView: View {
    // List of images
    private let images: [Image] = [
        Image(systemName: "icloud.and.arrow.up"),
        Image(systemName: "icloud.and.arrow.down"),
        Image(systemName: "cloud"),
        Image(systemName: "cloud.drizzle"),
        Image(systemName: "cloud.rain"),
        Image(systemName: "cloud.heavyrain")
    ]
    // Images and percent variable use for animating rain down
    private let imagesOrderDown = [2, 4, 5]
    @State var percentDown: Float = 0

    // Images and percent variable use for animating rain up
    @State var percentUp: Float = 0
    private let imagesOrderUp = [5, 3, 2]
    var body: some View {
        VStack {
            Spacer()
            HStack {
                Spacer()
                // tapping a button set percent to :
                // 0 = no animation (Animation.default)
                // 100 = animation with images
                Button {percentDown = percentDown < 50 ? 100 : 0} label: {
                    Image(systemName: "icloud.and.arrow.down")
                        .resizable()
                        .frame(width: 150, height: 150, alignment: .top)
                    .imageArrayAnimation(images: images, imagesOrder: imagesOrderDown, percent: percentDown)
                    .animation(percentDown <= 0 ? Animation.default : .linear(duration: 1).repeatForever(autoreverses: false), value: percentDown)
                    .border(.foreground, width: 2)
                    Spacer()
                }

                Button {percentUp = percentUp < 50 ? 100 : 0} label: {
                    Image(systemName: "icloud.and.arrow.up")
                        .resizable()
                        .frame(width: 150, height: 150, alignment: .top)
                    .imageArrayAnimation(images: images, imagesOrder: imagesOrderUp, percent: percentUp)
                    .animation(percentUp <= 0 ? Animation.default : .linear(duration: 1).repeatForever(autoreverses: false), value: percentUp)
                    .border(.foreground, width: 2)
                    Spacer()
                }
            }
            .frame(width: 100, height: 100, alignment: .center)
            Spacer()
        }
        
    }
}

struct ImageAnimation: AnimatableModifier {
    // Animation through th percent property
    // percent is converted into a position in an index array
    // this index value enable to choose whch image in the array
    // to display
    var animatableData: Float {
        get {
            percent
        }
        set {
            percent = newValue
        }
    }
    var images: [Image]
    var imgesOrder: [Int]
    var percent: Float
    var currentImageIndex: Int {
        if percent > 0 {
            let index = Int((percent / 100) *  Float(imgesOrder.count))
            print("% \(percent) \(index)")
            return imgesOrder[min(index, imgesOrder.count-1)]
        } else {
            return 0
        }
    }
    
    func body(content: Content) -> some View {
        ZStack(alignment: .top) {
            // for the animation to work content and image
            // needs to always be there
            // opacity enable to choose what to actually display
            content
                .opacity(percent == 0 ? 1 : 0)
            images[currentImageIndex]
                .resizable()
                .scaledToFit()
                .opacity(percent == 0 ? 0 : 1)
            
        }
    }
}

// extension to have mnamed modifier
extension View {
    func imageArrayAnimation(images: [Image], imagesOrder: [Int], percent: Float) -> some View {
        self.modifier(ImageAnimation(images: images, imgesOrder: imagesOrder, percent: percent))
    }
}

struct ImageArrayAnimationView_Previews: PreviewProvider {
    static var previews: some View {
        ImageArrayAnimationView()
    }
}

字符串

wlwcrazw

wlwcrazw4#

我有三个图像资产,我想动画顺序和重复命名:thinking1、thinking2和thinking3。根据nightwill的回答,这在iOS14.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()
    }
}

字符串

相关问题