はじめに
SwiftUIでGIFを使いたかったので使えるようにGIFViewを作ってみました。
サンプルアプリ
今回使用するGIF
SuperGSATBによるPixabayのGIF
実装
import SwiftUI
struct GIFView: View {
@State private var images: [Image] = []
@State private var gifCount: Int = 0
@State private var currentIndex: Int = 0
var gifName: String
var minimumInterval: Double
var body: some View {
TimelineView(.animation(minimumInterval: minimumInterval)) { context in
Group {
if images.isEmpty {
Text("エラー")
} else {
images[currentIndex]
.resizable()
.scaledToFit()
}
}
.onChange(of: context.date) {
if currentIndex == (gifCount - 1) {
currentIndex = 0
} else {
currentIndex += 1
}
}
}
.onAppear {
guard let bundleURL = Bundle.main.url(forResource: gifName, withExtension: "gif"),
let gifData = try? Data(contentsOf: bundleURL),
let source = CGImageSourceCreateWithData(gifData as CFData, nil)
else {
return
}
gifCount = CGImageSourceGetCount(source)
var cgImages: [CGImage?] = []
for i in 0..<gifCount {
cgImages.append(CGImageSourceCreateImageAtIndex(source, i, nil))
}
let uiImages = cgImages.compactMap({ $0 }).map({ UIImage(cgImage: $0) })
images = uiImages.map({ Image(uiImage: $0) })
}
}
}
使い方
使用側では、
gifName
はGIFのファイル名、
minimumInterval
はGIFの1枚の画像にかける秒数
を渡します。
import SwiftUI
struct ContentView: View {
var body: some View {
GIFView(gifName: "Heart", minimumInterval: 0.03)
.frame(width: 300, height: 300)
}
}
おわり
ロジック部分はもうちょいいい感じにできそうです。
currentIndex
で表示画像を管理しているのをもうちょい改善したいです。
改善案があれば編集リクエストがコメントください!
追記(2024/2/8)
コメントで教えてもらったもっと表示方法です!!
参考コード