feat: 动画后视频
This commit is contained in:
parent
34b6fa7894
commit
08a82386da
Binary file not shown.
|
Before Width: | Height: | Size: 4.3 MiB After Width: | Height: | Size: 2.8 MiB |
@ -501,6 +501,7 @@ struct BlindBoxView: View {
|
||||
self.displayImage = image
|
||||
self.aspectRatio = image.size.width / image.size.height
|
||||
self.isPortrait = image.size.height > image.size.width
|
||||
self.showScalingOverlay = true // 确保显示媒体内容
|
||||
}
|
||||
}
|
||||
}.resume()
|
||||
@ -526,11 +527,53 @@ struct BlindBoxView: View {
|
||||
isPortrait = height > width
|
||||
}
|
||||
|
||||
// Update the video player
|
||||
// 更新视频播放器
|
||||
videoPlayer = player
|
||||
videoPlayer?.play()
|
||||
showScalingOverlay = true // 确保显示媒体内容
|
||||
}
|
||||
|
||||
private func prepareVideo() {
|
||||
guard !videoURL.isEmpty, let url = URL(string: videoURL) else {
|
||||
print("⚠️ 视频URL无效或为空")
|
||||
return
|
||||
}
|
||||
|
||||
let asset = AVAsset(url: url)
|
||||
let playerItem = AVPlayerItem(asset: asset)
|
||||
let player = AVPlayer(playerItem: playerItem)
|
||||
|
||||
let videoTracks = asset.tracks(withMediaType: .video)
|
||||
if let videoTrack = videoTracks.first {
|
||||
let size = videoTrack.naturalSize.applying(videoTrack.preferredTransform)
|
||||
let width = abs(size.width)
|
||||
let height = abs(size.height)
|
||||
|
||||
aspectRatio = width / height
|
||||
isPortrait = height > width
|
||||
}
|
||||
|
||||
// 更新视频播放器
|
||||
videoPlayer = player
|
||||
}
|
||||
|
||||
private func prepareImage() {
|
||||
guard !imageURL.isEmpty, let url = URL(string: imageURL) else {
|
||||
print("⚠️ 图片URL无效或为空")
|
||||
return
|
||||
}
|
||||
|
||||
URLSession.shared.dataTask(with: url) { data, _, _ in
|
||||
if let data = data, let image = UIImage(data: data) {
|
||||
DispatchQueue.main.async {
|
||||
self.displayImage = image
|
||||
self.aspectRatio = image.size.width / image.size.height
|
||||
self.isPortrait = image.size.height > image.size.width
|
||||
}
|
||||
}
|
||||
}.resume()
|
||||
}
|
||||
|
||||
private func startScalingAnimation() {
|
||||
self.scale = 0.1
|
||||
self.showScalingOverlay = true
|
||||
@ -822,15 +865,30 @@ struct BlindBoxView: View {
|
||||
.frame(width: 300, height: 300)
|
||||
|
||||
case .opening:
|
||||
GIFView(name: "BlindOpen")
|
||||
.frame(width: 300, height: 300)
|
||||
.onAppear {
|
||||
self.loadMedia()
|
||||
// Start animation after media is loaded
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
|
||||
self.startScalingAnimation()
|
||||
ZStack {
|
||||
GIFView(name: "BlindOpen")
|
||||
.frame(width: 300, height: 300)
|
||||
.onAppear {
|
||||
print("开始播放开启动画")
|
||||
// 不在这里准备媒体,等待动画完成
|
||||
|
||||
// 2.5秒后开始显示媒体内容
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2.5) {
|
||||
// 准备并显示媒体
|
||||
if mediaType == .video {
|
||||
loadVideo()
|
||||
} else if mediaType == .image {
|
||||
loadImage()
|
||||
}
|
||||
|
||||
// 开始缩放动画
|
||||
withAnimation(.easeInOut(duration: 0.5)) {
|
||||
self.startScalingAnimation()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(width: 300, height: 300)
|
||||
|
||||
case .none:
|
||||
SVGImage(svgName: "BlindNone")
|
||||
|
||||
@ -162,6 +162,12 @@ struct BlindOutcomeView: View {
|
||||
}
|
||||
.padding(.bottom, 20)
|
||||
}
|
||||
.onDisappear {
|
||||
// Clean up video player when view disappears
|
||||
if case .video = media {
|
||||
isPlaying = false
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationBarHidden(true) // 确保隐藏系统导航栏
|
||||
.navigationBarBackButtonHidden(true) // 确保隐藏系统返回按钮
|
||||
@ -169,6 +175,9 @@ struct BlindOutcomeView: View {
|
||||
}
|
||||
.navigationViewStyle(StackNavigationViewStyle()) // 确保在iPad上也能正确显示
|
||||
.navigationBarHidden(true) // 额外确保隐藏导航栏
|
||||
.overlay(
|
||||
JoinModal(isPresented: $showIPListModal)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,14 +302,18 @@ struct VideoPlayerView: UIViewRepresentable {
|
||||
class PlayerView: UIView {
|
||||
private var player: AVPlayer?
|
||||
private var playerLayer: AVPlayerLayer?
|
||||
private var playerItem: AVPlayerItem?
|
||||
private var playerItemObserver: NSKeyValueObservation?
|
||||
|
||||
func setupPlayer(url: URL) {
|
||||
// Remove existing player if any
|
||||
playerLayer?.removeFromSuperlayer()
|
||||
// Clean up existing resources
|
||||
cleanup()
|
||||
|
||||
// Create new player
|
||||
let asset = AVAsset(url: url)
|
||||
let playerItem = AVPlayerItem(asset: asset)
|
||||
self.playerItem = playerItem
|
||||
|
||||
player = AVPlayer(playerItem: playerItem)
|
||||
|
||||
// Setup player layer
|
||||
@ -329,6 +342,27 @@ class PlayerView: UIView {
|
||||
player?.pause()
|
||||
}
|
||||
|
||||
private func cleanup() {
|
||||
// Remove observers
|
||||
if let playerItem = playerItem {
|
||||
NotificationCenter.default.removeObserver(self, name: .AVPlayerItemDidPlayToEndTime, object: playerItem)
|
||||
}
|
||||
|
||||
// Pause and clean up player
|
||||
player?.pause()
|
||||
player?.replaceCurrentItem(with: nil)
|
||||
player = nil
|
||||
|
||||
// Remove player layer
|
||||
playerLayer?.removeFromSuperlayer()
|
||||
playerLayer = nil
|
||||
|
||||
// Release player item
|
||||
playerItem?.cancelPendingSeeks()
|
||||
playerItem?.asset.cancelLoading()
|
||||
playerItem = nil
|
||||
}
|
||||
|
||||
@objc private func playerItemDidReachEnd() {
|
||||
player?.seek(to: .zero)
|
||||
player?.play()
|
||||
@ -340,9 +374,7 @@ class PlayerView: UIView {
|
||||
}
|
||||
|
||||
deinit {
|
||||
player?.pause()
|
||||
player?.replaceCurrentItem(with: nil)
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user