feat: 动效使用gif

This commit is contained in:
jinyaqiu 2025-08-28 14:12:55 +08:00
parent 5b83ace879
commit 023a64b947
4 changed files with 163 additions and 3 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 MiB

125
wake/Utils/GIFView.swift Normal file
View File

@ -0,0 +1,125 @@
import SwiftUI
import UIKit
struct GIFView: UIViewRepresentable {
let name: String
var onTap: (() -> Void)? = nil
func makeUIView(context: Context) -> UIImageView {
let imageView = UIImageView()
// GIF
guard let url = Bundle.main.url(forResource: name, withExtension: "gif"),
let data = try? Data(contentsOf: url),
let image = UIImage.gif(data: data) else {
return imageView
}
imageView.image = image
imageView.contentMode = .scaleAspectFit
//
if onTap != nil {
imageView.isUserInteractionEnabled = true
let tapGesture = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleTap))
imageView.addGestureRecognizer(tapGesture)
}
return imageView
}
func updateUIView(_ uiView: UIImageView, context: Context) {}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject {
var parent: GIFView
init(_ parent: GIFView) {
self.parent = parent
}
@objc func handleTap() {
parent.onTap?()
}
}
}
// UIImageGIF
extension UIImage {
static func gif(data: Data) -> UIImage? {
guard let source = CGImageSourceCreateWithData(data as CFData, nil) else {
print("无法创建CGImageSource")
return nil
}
let count = CGImageSourceGetCount(source)
var images = [UIImage]()
var duration: TimeInterval = 0
for i in 0..<count {
guard let cgImage = CGImageSourceCreateImageAtIndex(source, i, nil) else {
continue
}
duration += UIImage.gifDelayForImageAtIndex(source: source, index: i)
images.append(UIImage(cgImage: cgImage, scale: UIScreen.main.scale, orientation: .up))
}
if count == 1 {
return images.first
} else {
return UIImage.animatedImage(with: images, duration: duration)
}
}
static func gifDelayForImageAtIndex(source: CGImageSource, index: Int) -> TimeInterval {
var delay = 0.1
let cfProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil)
let properties = cfProperties as? [String: Any] ?? [:]
let gifProperties = properties[kCGImagePropertyGIFDictionary as String] as? [String: Any] ?? [:]
if let delayTime = gifProperties[kCGImagePropertyGIFUnclampedDelayTime as String] as? Double {
delay = delayTime
} else if let delayTime = gifProperties[kCGImagePropertyGIFDelayTime as String] as? Double {
delay = delayTime
}
if delay < 0.011 {
delay = 0.1
}
return delay
}
}
// 使 -
struct GIFWithTapExample: View {
@State private var tapCount = 0
var body: some View {
VStack(spacing: 20) {
Text("点击GIF图片")
.font(.title)
GIFView(name: "Blind") {
//
Router.shared.navigate(to: .blindBox(mediaType: .video))
}
.frame(width: 300, height: 300)
.border(Color.blue) //
Text("点击次数: \(tapCount)")
.font(.subheadline)
}
}
}
struct GIFWithTapExample_Previews: PreviewProvider {
static var previews: some View {
GIFWithTapExample()
}
}

View File

@ -136,29 +136,64 @@ struct MediaUploadView: View {
selectedMedia: Binding( selectedMedia: Binding(
get: { mediaPickerSelection }, get: { mediaPickerSelection },
set: { newSelections in set: { newSelections in
print("🔄 开始处理用户选择的媒体文件")
print("📌 新选择的媒体数量: \(newSelections.count)")
// ID
let existingMediaIDs = uploadManager.selectedMedia.map { $0.id }
print("📋 当前已选择的媒体ID: \(existingMediaIDs)")
// //
let newItems = newSelections.filter { newItem in let newItems = newSelections.filter { newItem in
!uploadManager.selectedMedia.contains { $0.id == newItem.id } let isNew = !uploadManager.selectedMedia.contains { $0.id == newItem.id }
print("🔍 检查媒体项 \(newItem.id) - \(isNew ? "新添加" : "已存在")")
return isNew
} }
print("✅ 过滤后的新添加媒体数量: \(newItems.count)")
if !newItems.isEmpty { if !newItems.isEmpty {
print("🔄 开始处理 \(newItems.count) 个新添加的媒体项...")
//
newItems.forEach { item in
switch item {
case .image(let uiImage):
print("🖼️ 添加图片 - 尺寸: \(uiImage.size.width)x\(uiImage.size.height)")
case .video(let url, _):
print("🎥 添加视频 - URL: \(url.lastPathComponent)")
}
}
// //
let newMedia = newItems + uploadManager.selectedMedia let newMedia = newItems + uploadManager.selectedMedia
print("📊 更新媒体列表 - 总数: \(newMedia.count) (新增: \(newItems.count), 原有: \(uploadManager.selectedMedia.count))")
uploadManager.clearAllMedia() uploadManager.clearAllMedia()
print("🧹 已清空现有媒体列表")
uploadManager.addMedia(newMedia) uploadManager.addMedia(newMedia)
print("✅ 已添加新媒体到上传管理器")
// //
if selectedIndices.isEmpty { if selectedIndices.isEmpty {
selectedIndices = [0] // selectedIndices = [0]
selectedMedia = newItems.first selectedMedia = newItems.first
print("👆 自动选择第一个新增的媒体项: \(selectedMedia?.id ?? "nil")")
} else {
print(" 保持当前选中的媒体项")
} }
// //
print("🚀 开始上传新添加的媒体...")
uploadManager.startUpload() uploadManager.startUpload()
} else {
print(" 没有新的媒体项需要添加")
} }
// //
mediaPickerSelection = [] mediaPickerSelection = []
print("🔄 已重置媒体选择器状态")
} }
), ),
imageSelectionLimit: max(0, 20 - uploadManager.selectedMedia.filter { imageSelectionLimit: max(0, 20 - uploadManager.selectedMedia.filter {

View File

@ -48,7 +48,7 @@ struct WakeApp: App {
// userInfo // userInfo
// ContentView() // ContentView()
// .environmentObject(authState) // .environmentObject(authState)
UserInfo() MediaUploadView()
.environmentObject(authState) .environmentObject(authState)
} else { } else {
// //