import SwiftUI
struct ContentView: View {
private let letters: [String] = ["A", "B", "C"]
private let numbers: [Int] = [
4, 5, 21, // A, B, C
23, 27, 36, // A, B, C
37, 52, 59 // A, B, C
]
@State private var randomNumber: Int = 0
@State private var rotation: CGFloat = 0.0
@State private var started: Bool = false
var body: some View {
VStack {
ZStack {
ZStack {
Circle()
.foregroundColor(.blue)
ForEach(letters.indices) { i in
Text(letters[i])
.foregroundColor(.white)
.offset(x: 0, y: -110)
.rotationEffect(.degrees(Double(i * (360 / letters.count))))
}
}
.frame(width: 250, height: 250, alignment: .center)
.rotationEffect(.degrees(rotation))
VStack {
Text("Rotation: \(rotation, specifier: "%.2f")")
Text("Number: \(randomNumber)")
Text("Closest: \(closest(to: randomNumber))")
}
}
Spacer()
.frame(height: 50)
Button(started ? "Stop" : "Start", action: started ? stop : start)
.buttonStyle(.borderedProminent)
.tint(started ? .red : .blue)
}
}
private func start() {
started = true
loop()
}
private func stop() {
started = false
}
private func loop() {
if !started { return }
randomNumber = .random(in: numbers.min()!...numbers.max()!)
withAnimation {
rotation = CGFloat(0)
}
DispatchQueue.main.asyncAfter(deadline: .now() 1, execute: loop)
}
private func closest(to x: Int) -> Int {
return numbers.enumerated().min(by: { abs($0.1 - x) < abs($1.1 - x)})!.element
}
}
Hello, I want to rotate the zstack according to randomNumber value to match the letter number in array for example if randomNumber = 30 closest number = 27 which is labeled B in the circle I want to rotate the zstack so the letter B point to north but a little offset because the number is 30 not 27 exactly
The code above is example the calculation happens in loop function inside withAnimation brackets
Thank you
CodePudding user response:
Here is a proposal for your loop, so the rotation picks the closest number in the array:
randomNumber = .random(in: numbers.min()!...numbers.max()!)
let differences = numbers.compactMap { abs($0 - randomNumber) }.sorted { $0 < $1 }
let closest = randomNumber - (differences.first ?? 0)
withAnimation {
if numbers.contains(closest) {
rotation = closest
} else {
rotation = randomNumber (differences.first ?? 0)
}
}
Just remember to use the proper types (Int, CGFloat…).