feat: 弹窗阴影

This commit is contained in:
jinyaqiu 2025-09-02 15:37:05 +08:00
parent bd603a7c19
commit 2d2a751a10
6 changed files with 108 additions and 22 deletions

View File

@ -903,7 +903,6 @@ struct BlindBoxView: View {
memberDate: $memberDate memberDate: $memberDate
) )
} }
.shadow(color: .black.opacity(0.3), radius: 10, x: 5, y: 0)
.offset(x: showSettings ? UIScreen.main.bounds.width : 0) .offset(x: showSettings ? UIScreen.main.bounds.width : 0)
.animation(.spring(response: 0.6, dampingFraction: 0.8), value: showSettings) .animation(.spring(response: 0.6, dampingFraction: 0.8), value: showSettings)

View File

@ -0,0 +1,71 @@
import SwiftUI
import WebKit
struct SVGImageHtml: UIViewRepresentable {
let svgName: String
func makeUIView(context: Context) -> WKWebView {
let webView = WKWebView()
webView.isOpaque = false
webView.backgroundColor = .clear
webView.scrollView.isScrollEnabled = false
webView.scrollView.contentInsetAdjustmentBehavior = .never
// 1. Get the URL for the SVG file
guard let path = Bundle.main.path(forResource: svgName, ofType: "svg") else {
print("❌ Cannot find SVG file: \(svgName).svg in bundle")
return webView
}
let fileURL = URL(fileURLWithPath: path)
do {
// 2. Read the SVG content directly
let svgString = try String(contentsOf: fileURL, encoding: .utf8)
// 3. Create HTML with inline SVG for better reliability
let htmlString = """
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<style>
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
background-color: transparent;
display: flex;
justify-content: center;
align-items: center;
}
svg {
max-width: 100%;
max-height: 100%;
}
</style>
</head>
<body>
\(svgString)
</body>
</html>
"""
// 4. Load the HTML with base URL as the main bundle's resource path
if let resourcePath = Bundle.main.resourceURL {
webView.loadHTMLString(htmlString, baseURL: resourcePath)
} else {
webView.loadHTMLString(htmlString, baseURL: nil)
}
} catch {
print("❌ Error loading SVG file: \(error.localizedDescription)")
}
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {}
}

View File

@ -8,7 +8,7 @@ struct SlideInModal<Content: View>: View {
// - // -
private let animation = Animation.spring( private let animation = Animation.spring(
response: 0.8, // 使 response: 0.8, // 使
dampingFraction: 0.6, // 使 dampingFraction: 1, // 使
blendDuration: 0.8 // 使 blendDuration: 0.8 // 使
) )
@ -28,21 +28,35 @@ struct SlideInModal<Content: View>: View {
} }
} }
// //
VStack(spacing: 0) { ZStack(alignment: .leading) {
// //
Color.clear VStack(spacing: 0) {
.frame(height: UIApplication.shared.windows.first?.safeAreaInsets.top ?? 0) //
Color.clear
// .frame(height: UIApplication.shared.windows.first?.safeAreaInsets.top ?? 0)
content()
.frame(maxWidth: .infinity, maxHeight: .infinity) //
.padding(.bottom, UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0) content()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.padding(.bottom, UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0)
}
.frame(width: UIScreen.main.bounds.width * 0.8)
.frame(maxHeight: .infinity)
.background(Color(.systemBackground))
.edgesIgnoringSafeArea(.vertical)
} }
.frame(width: UIScreen.main.bounds.width * 0.8) //
.frame(maxHeight: .infinity) .background(
.background(Color(.systemBackground)) RoundedRectangle(cornerRadius: 0)
.edgesIgnoringSafeArea(.vertical) .fill(Color(.systemBackground))
.shadow(
color: .black.opacity(0.3),
radius: 10,
x: 5,
y: 0
)
)
.offset(x: isPresented ? 0 : -UIScreen.main.bounds.width) .offset(x: isPresented ? 0 : -UIScreen.main.bounds.width)
.zIndex(2) .zIndex(2)
.transition(.move(edge: .leading)) .transition(.move(edge: .leading))

View File

@ -71,6 +71,9 @@ struct UserProfileModal: View {
.foregroundColor(.blue) .foregroundColor(.blue)
} }
} }
.onTapGesture {
Router.shared.navigate(to: .userInfo)
}
} else { } else {
Image(systemName: "person.circle.fill") Image(systemName: "person.circle.fill")
.resizable() .resizable()

View File

@ -50,18 +50,17 @@ public struct AvatarPicker: View {
if let selectedImage = selectedImage { if let selectedImage = selectedImage {
Image(uiImage: selectedImage) Image(uiImage: selectedImage)
.resizable() .resizable()
.scaledToFill() .aspectRatio(contentMode: .fill)
.frame(width: 225, height: 225) .frame(width: 225, height: 225)
.scaleEffect(scaleFactor) .clipShape(RoundedRectangle(cornerRadius: 20))
.clipShape(RoundedRectangle(cornerRadius: 20 * scaleFactor))
.overlay( .overlay(
RoundedRectangle(cornerRadius: 20) RoundedRectangle(cornerRadius: 20)
.stroke(Color.themePrimary, lineWidth: borderWidth) .stroke(Color.themePrimary, lineWidth: borderWidth)
.scaleEffect(scaleFactor)
) )
.scaleEffect(scaleFactor)
} else { } else {
// Default SVG avatar with animated dashed border // Default SVG avatar with animated dashed border
SVGImage(svgName: "IP") SVGImageHtml(svgName: "IP")
.frame(width: 225, height: 225) .frame(width: 225, height: 225)
.scaleEffect(scaleFactor) .scaleEffect(scaleFactor)
.contentShape(Rectangle()) .contentShape(Rectangle())

View File

@ -599,7 +599,7 @@ struct UploadPromptView: View {
var body: some View { var body: some View {
Button(action: { showMediaPicker = true }) { Button(action: { showMediaPicker = true }) {
// //
SVGImage(svgName: "IP") SVGImageHtml(svgName: "IP")
.frame(width: 225, height: 225) .frame(width: 225, height: 225)
.contentShape(Rectangle()) .contentShape(Rectangle())
.overlay( .overlay(