CasinoGames/Baccarat/Views/Chips/ChipView.swift

117 lines
3.8 KiB
Swift

//
// ChipView.swift
// Baccarat
//
// A realistic casino-style betting chip.
//
import SwiftUI
/// A realistic casino-style betting chip.
struct ChipView: View {
let denomination: ChipDenomination
let size: CGFloat
var isSelected: Bool = false
init(denomination: ChipDenomination, size: CGFloat = 60, isSelected: Bool = false) {
self.denomination = denomination
self.size = size
self.isSelected = isSelected
}
var body: some View {
ZStack {
// Base circle with gradient
Circle()
.fill(
RadialGradient(
colors: [
denomination.secondaryColor,
denomination.primaryColor,
denomination.primaryColor.opacity(0.8)
],
center: .topLeading,
startRadius: 0,
endRadius: size
)
)
// Edge stripes pattern
ChipEdgePattern(stripeColor: denomination.stripeColor)
.clipShape(.circle)
// Inner circle
Circle()
.fill(
RadialGradient(
colors: [
denomination.secondaryColor,
denomination.primaryColor
],
center: .topLeading,
startRadius: 0,
endRadius: size * 0.4
)
)
.frame(width: size * 0.65, height: size * 0.65)
// Inner border
Circle()
.strokeBorder(
denomination.stripeColor.opacity(0.8),
lineWidth: Design.LineWidth.medium
)
.frame(width: size * 0.65, height: size * 0.65)
// Denomination text
Text(denomination.displayText)
.font(.system(size: size * 0.25, weight: .heavy, design: .rounded))
.foregroundStyle(denomination.stripeColor)
.shadow(color: .black.opacity(Design.Opacity.light), radius: 1, x: 1, y: 1)
// Outer border
Circle()
.strokeBorder(
LinearGradient(
colors: [
Color.white.opacity(Design.Opacity.overlay),
Color.black.opacity(Design.Opacity.light)
],
startPoint: .topLeading,
endPoint: .bottomTrailing
),
lineWidth: Design.LineWidth.medium
)
// Selection glow
if isSelected {
Circle()
.strokeBorder(Color.yellow, lineWidth: Design.LineWidth.thick)
.frame(width: size + 6, height: size + 6)
}
}
.frame(width: size, height: size)
.shadow(color: .black.opacity(Design.Opacity.overlay), radius: isSelected ? 8 : 4, x: 2, y: 3)
.scaleEffect(isSelected ? 1.1 : 1.0)
.animation(.spring(duration: 0.2), value: isSelected)
}
}
#Preview {
ZStack {
Color.Table.preview
.ignoresSafeArea()
VStack(spacing: Design.Spacing.xxxLarge) {
HStack(spacing: Design.Spacing.xLarge) {
ForEach(ChipDenomination.allCases) { denom in
ChipView(denomination: denom, size: Design.Size.chipSelector)
}
}
ChipView(denomination: .hundred, size: 80, isSelected: true)
}
}
}