117 lines
3.8 KiB
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)
|
|
}
|
|
}
|
|
}
|
|
|