You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
4.2 KiB
152 lines
4.2 KiB
import SwiftUI
|
|
|
|
// MARK: - 扫描线视图
|
|
struct ScanningLineView: View {
|
|
@EnvironmentObject var languageManager: LanguageManager
|
|
let style: ScanningLineStyle
|
|
|
|
var body: some View {
|
|
Group {
|
|
switch style {
|
|
case .modern:
|
|
ModernScanningLine()
|
|
case .classic:
|
|
ClassicScanningLine()
|
|
case .neon:
|
|
NeonScanningLine()
|
|
case .minimal:
|
|
MinimalScanningLine()
|
|
case .retro:
|
|
RetroScanningLine()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - 扫描线样式枚举
|
|
enum ScanningLineStyle: String, CaseIterable {
|
|
case modern = "style_modern"
|
|
case classic = "style_classic"
|
|
case neon = "style_neon"
|
|
case minimal = "style_minimal"
|
|
case retro = "style_retro"
|
|
|
|
var localizedName: String {
|
|
switch self {
|
|
case .modern: return "style_modern".localized
|
|
case .classic: return "style_classic".localized
|
|
case .neon: return "style_neon".localized
|
|
case .minimal: return "style_minimal".localized
|
|
case .retro: return "style_retro".localized
|
|
}
|
|
}
|
|
|
|
func getLocalizedName(languageManager: LanguageManager) -> String {
|
|
switch self {
|
|
case .modern: return languageManager.localizedString(for: "style_modern")
|
|
case .classic: return languageManager.localizedString(for: "style_classic")
|
|
case .neon: return languageManager.localizedString(for: "style_neon")
|
|
case .minimal: return languageManager.localizedString(for: "style_minimal")
|
|
case .retro: return languageManager.localizedString(for: "style_retro")
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - 扫描线动画修饰符
|
|
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
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - 脉冲动画修饰符
|
|
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
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - 现代扫描线
|
|
struct ModernScanningLine: View {
|
|
var body: some View {
|
|
Rectangle()
|
|
.fill(
|
|
LinearGradient(
|
|
colors: [.blue, .cyan, .blue],
|
|
startPoint: .leading,
|
|
endPoint: .trailing
|
|
)
|
|
)
|
|
.frame(width: 200, height: 3)
|
|
.shadow(color: .blue, radius: 5, x: 0, y: 0)
|
|
.modifier(ScanningLineModifier())
|
|
}
|
|
}
|
|
|
|
// MARK: - 经典扫描线
|
|
struct ClassicScanningLine: View {
|
|
var body: some View {
|
|
Rectangle()
|
|
.fill(Color.green)
|
|
.frame(width: 150, height: 2)
|
|
.modifier(ScanningLineModifier())
|
|
}
|
|
}
|
|
|
|
// MARK: - 霓虹扫描线
|
|
struct NeonScanningLine: View {
|
|
var body: some View {
|
|
Rectangle()
|
|
.fill(Color.purple)
|
|
.frame(width: 180, height: 4)
|
|
.shadow(color: .purple, radius: 8, x: 0, y: 0)
|
|
.modifier(ScanningLineModifier())
|
|
}
|
|
}
|
|
|
|
// MARK: - 极简扫描线
|
|
struct MinimalScanningLine: View {
|
|
var body: some View {
|
|
Rectangle()
|
|
.fill(Color.white)
|
|
.frame(width: 100, height: 1)
|
|
.modifier(ScanningLineModifier())
|
|
}
|
|
}
|
|
|
|
// MARK: - 复古扫描线
|
|
struct RetroScanningLine: View {
|
|
var body: some View {
|
|
HStack(spacing: 2) {
|
|
ForEach(0..<5, id: \.self) { _ in
|
|
Rectangle()
|
|
.fill(Color.orange)
|
|
.frame(width: 2, height: 20)
|
|
}
|
|
}
|
|
.modifier(ScanningLineModifier())
|
|
}
|
|
} |