Skip to content

Instantly share code, notes, and snippets.

@mergesort
Last active December 18, 2023 02:34
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mergesort/bee3a79646a2f38b63c194afbee589aa to your computer and use it in GitHub Desktop.
Save mergesort/bee3a79646a2f38b63c194afbee589aa to your computer and use it in GitHub Desktop.
A SwiftUI prototype animation for adding/removing players from a game
import SwiftUI
let colors = [
Color.pink,
Color.blue,
Color.green,
Color.orange,
Color.purple,
Color.black,
]
struct ContentView: View {
@State
var playerCount: Int
var body: some View {
VStack {
HStack(spacing: 0) {
ForEach(Array(0..<playerCount), id: \.self) { index in
PlayerView(
backgroundColor: colors[index]
)
.transition(AnyTransition.move(edge: .trailing))
.animation(.easeInOut)
}
}
.frame(height: 144.0)
CounterView(playerCount: $playerCount)
}
}
}
struct PlayerView: View {
var backgroundColor: Color
var body: some View {
ZStack {
Rectangle()
.fill(self.backgroundColor.opacity(0.25))
GeometryReader { proxy in
Image(systemName: "gamecontroller.fill")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: proxy.smallerDimension * 3/4, height: proxy.smallerDimension * 3/4)
.foregroundColor(self.backgroundColor)
}
}
}
}
struct CounterView: View {
@Binding
var playerCount: Int
var body: some View {
let minusDisabled = self.playerCount <= 1
let plusDisabled = self.playerCount >= colors.count
return HStack(spacing: 16.0) {
Text("Number of players")
.font(.title)
.bold()
Button(action: {
if self.playerCount > 1 {
self.playerCount -= 1
}
}, label: {
Image(systemName: "minus.circle.fill")
.resizable()
.frame(width: 36.0, height: 36.0)
.foregroundColor(minusDisabled ? Color.gray.opacity(0.1) : Color.gray.opacity(0.6))
})
.disabled(minusDisabled)
Text("\(self.playerCount)")
.font(.title)
.bold()
Button(action: {
if self.playerCount < colors.count {
self.playerCount += 1
}
}, label: {
Image(systemName: "plus.circle.fill")
.resizable()
.frame(width: 36.0, height: 36.0)
.foregroundColor(plusDisabled ? Color.gray.opacity(0.1) : Color.gray.opacity(0.6))
})
.disabled(plusDisabled)
}
}
}
extension GeometryProxy {
var smallerDimension: CGFloat {
min(self.size.width, self.size.height)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment