diff --git a/MyQrCode.xcodeproj/xcuserdata/yc.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/MyQrCode.xcodeproj/xcuserdata/yc.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index e5aeb5c..b44f012 100644 --- a/MyQrCode.xcodeproj/xcuserdata/yc.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/MyQrCode.xcodeproj/xcuserdata/yc.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -14,8 +14,8 @@ filePath = "MyQrCode/ScannerView.swift" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "154" - endingLineNumber = "154" + startingLineNumber = "145" + endingLineNumber = "145" landmarkName = "body" landmarkType = "24"> @@ -30,8 +30,8 @@ filePath = "MyQrCode/ScannerView.swift" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "155" - endingLineNumber = "155" + startingLineNumber = "146" + endingLineNumber = "146" landmarkName = "body" landmarkType = "24"> @@ -46,8 +46,8 @@ filePath = "MyQrCode/ScannerView.swift" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "147" - endingLineNumber = "147" + startingLineNumber = "138" + endingLineNumber = "138" landmarkName = "body" landmarkType = "24"> @@ -62,8 +62,8 @@ filePath = "MyQrCode/ScannerView.swift" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "175" - endingLineNumber = "175" + startingLineNumber = "166" + endingLineNumber = "166" landmarkName = "body" landmarkType = "24"> diff --git a/MyQrCode/ContentView.swift b/MyQrCode/ContentView.swift index 054140b..c42826f 100644 --- a/MyQrCode/ContentView.swift +++ b/MyQrCode/ContentView.swift @@ -64,8 +64,12 @@ struct ContentView: View { } } } -} +} -#Preview { - ContentView() +#if DEBUG +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } } +#endif diff --git a/MyQrCode/ScannerView.swift b/MyQrCode/ScannerView.swift index c24aaf1..e71ae00 100644 --- a/MyQrCode/ScannerView.swift +++ b/MyQrCode/ScannerView.swift @@ -1,6 +1,7 @@ import SwiftUI import AVFoundation -internal import Combine +import UIKit +import Combine // 通知名称扩展 extension Notification.Name { @@ -21,6 +22,7 @@ struct ScannerView: View { @State private var showPreviewPause = false @State private var previewLayer: AVCaptureVideoPreviewLayer? @State private var screenOrientation = UIDevice.current.orientation + @State private var selectedScanningStyle: ScanningLineStyle = .modern var body: some View { ZStack { @@ -32,33 +34,12 @@ struct ScannerView: View { VStack { Spacer() - // 扫描框 - ZStack { - RoundedRectangle(cornerRadius: 20) - .stroke(Color.white, lineWidth: 3) - .frame(width: 250, height: 250) - .background(Color.black.opacity(0.3)) - .cornerRadius(20) - - // 扫描线动画 - if !showPreviewPause { - Rectangle() - .fill(LinearGradient( - colors: [Color.clear, Color.green, Color.clear], - startPoint: .top, - endPoint: .bottom - )) - .frame(width: 250, height: 2) - .offset(y: -125) - .animation( - Animation.linear(duration: 2) - .repeatForever(autoreverses: false), - value: UUID() - ) - } + // 扫描线组件 + if !showPreviewPause { + ScanningLineView(style: selectedScanningStyle) } - // 提示文本 + // 提示文本 if showPreviewPause { VStack(spacing: 8) { Text("检测到条码") @@ -78,15 +59,33 @@ struct ScannerView: View { .padding(.top, 20) } else { Text("将二维码或条形码放入框内") - .foregroundColor(.white) - .font(.headline) - .padding(.top, 20) + .foregroundColor(.white) + .font(.headline) + .padding(.top, 20) } Spacer() // 底部按钮区域 VStack(spacing: 15) { + // 扫描线样式选择器 + if !showPreviewPause { + HStack(spacing: 10) { + ForEach(ScanningLineStyle.allCases, id: \.self) { style in + Button(style.rawValue) { + selectedScanningStyle = style + } + .foregroundColor(.white) + .padding(.horizontal, 8) + .padding(.vertical, 4) + .background(selectedScanningStyle == style ? Color.green : Color.gray.opacity(0.6)) + .cornerRadius(8) + .font(.caption) + } + } + .padding(.bottom, 10) + } + if showPreviewPause { // 预览暂停时的按钮 Button("重新扫描") { @@ -143,8 +142,6 @@ struct ScannerView: View { Spacer() } } - - } .onAppear { scannerViewModel.startScanning() @@ -160,6 +157,7 @@ struct ScannerView: View { Text("您的设备不支持扫描二维码。请使用带相机的设备。") } + .onReceive(scannerViewModel.$detectedCodes) { codes in if !codes.isEmpty { print("检测到条码数量: \(codes.count)") @@ -260,6 +258,8 @@ class ScannerViewModel: NSObject, ObservableObject, AVCaptureMetadataOutputObjec setupCaptureSession() } + // MARK: - 相机设置 + private func setupCaptureSession() { captureSession = AVCaptureSession() @@ -471,7 +471,216 @@ struct CodePositionMarker: View { } +// 扫描线动画修饰符 +struct ScanningLineModifier: ViewModifier { + @State private var isAnimating = false + + func body(content: Content) -> some View { + content + .offset(y: isAnimating ? 150 : -150) + .onAppear { + withAnimation( + Animation.linear(duration: 2) + .repeatForever(autoreverses: false) + ) { + isAnimating = true + } + } + } +} + +// 脉冲动画修饰符 +struct PulseAnimationModifier: ViewModifier { + @State private var isPulsing = false + + func body(content: Content) -> some View { + content + .scaleEffect(isPulsing ? 1.5 : 1.0) + .opacity(isPulsing ? 0.0 : 0.8) + .onAppear { + withAnimation( + Animation.easeInOut(duration: 1.5) + .repeatForever(autoreverses: false) + ) { + isPulsing = true + } + } + } +} + +// 扫描线样式枚举 +enum ScanningLineStyle: String, CaseIterable { + case modern = "现代科技" + case classic = "经典简约" + case neon = "霓虹炫酷" + case minimal = "极简主义" + case retro = "复古风格" +} -#Preview { - ScannerView() -} +// 扫描线组件 +struct ScanningLineView: View { + let style: ScanningLineStyle + + var body: some View { + switch style { + case .modern: + ModernScanningLine() + case .classic: + ClassicScanningLine() + case .neon: + NeonScanningLine() + case .minimal: + MinimalScanningLine() + case .retro: + RetroScanningLine() + } + } +} + +// 现代科技风格扫描线 +struct ModernScanningLine: View { + var body: some View { + ZStack { + // 外发光效果 + Rectangle() + .fill(LinearGradient( + colors: [Color.clear, Color.green.opacity(0.3), Color.clear], + startPoint: .top, + endPoint: .bottom + )) + .frame(width: 320, height: 8) + .blur(radius: 3) + + // 主扫描线 + Rectangle() + .fill(LinearGradient( + colors: [Color.clear, Color.green, Color.clear], + startPoint: .top, + endPoint: .bottom + )) + .frame(width: 300, height: 3) + .shadow(color: .green, radius: 2, x: 0, y: 0) + + // 内发光效果 + Rectangle() + .fill(LinearGradient( + colors: [Color.clear, Color.green.opacity(0.8), Color.clear], + startPoint: .top, + endPoint: .bottom + )) + .frame(width: 300, height: 1) + .blur(radius: 1) + + // 中心扫描点 + Circle() + .fill(Color.green) + .frame(width: 8, height: 8) + .shadow(color: .green, radius: 4, x: 0, y: 0) + + // 扫描点外圈 + Circle() + .stroke(Color.green.opacity(0.6), lineWidth: 2) + .frame(width: 16, height: 16) + + // 脉冲效果 + Circle() + .stroke(Color.green.opacity(0.4), lineWidth: 1) + .frame(width: 24, height: 24) + .scaleEffect(1.0) + .opacity(0.8) + .modifier(PulseAnimationModifier()) + } + .modifier(ScanningLineModifier()) + } +} + +// 经典简约风格扫描线 +struct ClassicScanningLine: View { + var body: some View { + Rectangle() + .fill(Color.green) + .frame(width: 300, height: 2) + .modifier(ScanningLineModifier()) + } +} + +// 霓虹炫酷风格扫描线 +struct NeonScanningLine: View { + var body: some View { + ZStack { + // 霓虹外发光 + Rectangle() + .fill(LinearGradient( + colors: [Color.clear, Color.cyan.opacity(0.6), Color.clear], + startPoint: .top, + endPoint: .bottom + )) + .frame(width: 340, height: 12) + .blur(radius: 4) + + // 主扫描线 + Rectangle() + .fill(LinearGradient( + colors: [Color.cyan, Color.blue, Color.cyan], + startPoint: .leading, + endPoint: .trailing + )) + .frame(width: 300, height: 4) + .shadow(color: .cyan, radius: 6, x: 0, y: 0) + + // 中心亮点 + Circle() + .fill(Color.white) + .frame(width: 6, height: 6) + .shadow(color: .white, radius: 8, x: 0, y: 0) + } + .modifier(ScanningLineModifier()) + } +} + +// 极简主义风格扫描线 +struct MinimalScanningLine: View { + var body: some View { + Rectangle() + .fill(Color.white.opacity(0.8)) + .frame(width: 280, height: 1) + .modifier(ScanningLineModifier()) + } +} + +// 复古风格扫描线 +struct RetroScanningLine: View { + var body: some View { + ZStack { + // 复古扫描线 + Rectangle() + .fill(LinearGradient( + colors: [Color.clear, Color.orange, Color.clear], + startPoint: .top, + endPoint: .bottom + )) + .frame(width: 300, height: 3) + .overlay( + Rectangle() + .stroke(Color.orange, lineWidth: 1) + .frame(width: 300, height: 3) + ) + + // 复古扫描点 + Circle() + .fill(Color.orange) + .frame(width: 4, height: 4) + } + .modifier(ScanningLineModifier()) + } +} + + + +#if DEBUG +struct ScannerView_Previews: PreviewProvider { + static var previews: some View { + ScannerView() + } +} +#endif