99 lines
3.3 KiB
Swift
99 lines
3.3 KiB
Swift
import SwiftUI
|
||
import UIKit
|
||
import AVKit
|
||
|
||
// 展示媒体的扩散缩放覆盖层(视频/图片)
|
||
struct BlindBoxMediaOverlay: View {
|
||
let mediaType: BlindBoxMediaType
|
||
@Binding var player: AVPlayer?
|
||
let displayImage: UIImage?
|
||
let isPortrait: Bool
|
||
let aspectRatio: CGFloat
|
||
@Binding var scale: CGFloat
|
||
let onBack: () -> Void
|
||
|
||
@State private var showControls: Bool = false
|
||
|
||
private var scaledWidth: CGFloat {
|
||
if isPortrait {
|
||
return UIScreen.main.bounds.height * scale * 1 / aspectRatio
|
||
} else {
|
||
return UIScreen.main.bounds.width * scale
|
||
}
|
||
}
|
||
|
||
private var scaledHeight: CGFloat {
|
||
if isPortrait {
|
||
return UIScreen.main.bounds.height * scale
|
||
} else {
|
||
return UIScreen.main.bounds.width * scale * 1 / aspectRatio
|
||
}
|
||
}
|
||
|
||
var body: some View {
|
||
ZStack {
|
||
VisualEffectView(effect: UIBlurEffect(style: .systemUltraThinMaterialLight))
|
||
.opacity(0.3)
|
||
.edgesIgnoringSafeArea(.all)
|
||
|
||
Group {
|
||
if mediaType == .all, player != nil {
|
||
AVPlayerController(player: $player)
|
||
.frame(width: scaledWidth, height: scaledHeight)
|
||
.opacity(scale == 1 ? 1 : 0.7)
|
||
.onAppear { player?.play() }
|
||
} else if mediaType == .image, let image = displayImage {
|
||
Image(uiImage: image)
|
||
.resizable()
|
||
.scaledToFit()
|
||
.frame(width: scaledWidth, height: scaledHeight)
|
||
.opacity(scale == 1 ? 1 : 0.7)
|
||
}
|
||
}
|
||
.contentShape(Rectangle())
|
||
.onTapGesture {
|
||
withAnimation(.easeInOut(duration: 0.1)) {
|
||
showControls.toggle()
|
||
}
|
||
}
|
||
|
||
if showControls {
|
||
VStack {
|
||
HStack {
|
||
Button(action: onBack) {
|
||
Image(systemName: "chevron.left")
|
||
.font(.system(size: 24))
|
||
.foregroundColor(.black)
|
||
}
|
||
Spacer()
|
||
}
|
||
Spacer()
|
||
}
|
||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||
.padding(.top, 50)
|
||
.padding(.leading, 20)
|
||
.zIndex(1000)
|
||
.transition(.opacity)
|
||
.onAppear {
|
||
// 2秒后显示按钮(首显时)
|
||
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
||
withAnimation(.easeInOut(duration: 0.3)) {
|
||
showControls = true
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||
.animation(.easeInOut(duration: 1.0), value: scale)
|
||
.ignoresSafeArea()
|
||
.onAppear {
|
||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
|
||
withAnimation(.spring(response: 2.5, dampingFraction: 0.6, blendDuration: 1.0)) {
|
||
self.scale = 1.0
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|