Im starting out as a SwiftUI Xcode developer and I somehow can’t get this fixed and it’s so annoying. Basically the below code is a kind of timing game where you have to try to stop the slider/indicator on the green rectangle. That’s when you win. This already works, but the movement of the slider/indicator is so slow and just not smooth, and every time I change around certain numbers, the slider/indicator behaves very weirdly. I just want it to be fast enough so it’s a challenge and I also want a very smooth movement. I tried with other animation variants, but I then I cant get the exact positioning of the slider/indicator when its stopped.
import SwiftUI
struct Slider: View {
@State private var sliderPosition: CGFloat = 0
@State private var isSliding: Bool = false
@State private var didWin: Bool = false
@State private var didYellow: Bool = false
@State private var movingRight: Bool = true
let timer = Timer.publish(every: 0.01, on: .main, in: .common).autoconnect()
let mainRectWidth: CGFloat = 300
let targetZoneStart: CGFloat = 125
let targetZoneWidth: CGFloat = 50
let targetZoneStart2: CGFloat = 75
let targetZoneWidth2: CGFloat = 150
let sliderSpeed: CGFloat = 2
var body: some View {
VStack {
ZStack(alignment: .leading) {
Rectangle()
.fill(Color.gray)
.frame(width: mainRectWidth, height: 50)
Rectangle()
.fill(Color.yellow)
.frame(width: targetZoneWidth2, height: 50)
.offset(x: targetZoneStart2)
Rectangle()
.fill(Color.green)
.frame(width: targetZoneWidth, height: 50)
.offset(x: targetZoneStart)
Rectangle()
.fill(Color.blue)
.frame(width: 10, height: 50)
.offset(x: sliderPosition)
.animation(.linear(duration: 0.01), value: sliderPosition)
.onReceive(timer) { _ in
if isSliding {
if movingRight {
sliderPosition += sliderSpeed
if sliderPosition >= mainRectWidth - 10 {
movingRight = false
}
} else {
sliderPosition -= sliderSpeed
if sliderPosition <= 0 {
movingRight = true
}
}
}
}
}
.onTapGesture {
if isSliding {
isSliding = false
checkIfWin()
checkIfYellow()
}
}
if didWin {
Text("You Win!")
.font(.largeTitle)
.foregroundColor(.green)
} else if didYellow && !didWin {
Text("You Yellow!")
.font(.largeTitle)
.foregroundColor(.yellow)
} else if !didYellow && !didWin {
Text("You Lose!")
.font(.largeTitle)
.foregroundColor(.red)
}
if !isSliding {
Button(action: startGame) {
Text("Start")
.font(.largeTitle)
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
.padding()
}
}
.padding()
}
func checkIfWin() {
if sliderPosition >= targetZoneStart && sliderPosition <= (targetZoneStart + targetZoneWidth) {
didWin = true
}
}
func checkIfYellow() {
if sliderPosition >= targetZoneStart2 && sliderPosition <= (targetZoneStart2 + targetZoneWidth2) {
didYellow = true
}
}
func startGame() {
sliderPosition = 0
isSliding = true
didWin = false
didYellow = false
movingRight = true
}
}
struct Slider_Preview: PreviewProvider {
static var previews: some View {
Slider()
}
}
I tried everything but I cant get it to work.
David Johansen is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.