旋转到最接近的值标签

Rotation to closest value label

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([=10=].1 - x) < abs(.1 - x)})!.element
    }
}

您好, 例如,我想根据 randomNumber 值旋转 zstack 以匹配数组中的字母编号 如果随机数 = 30 最接近的数字 = 27 在圆圈中标记为 B 我想旋转 zstack,使字母 B 指向北方但有一点偏移,因为数字是 30 而不是 27

上面的代码是示例,计算发生在 withAnimation 括号内的循环函数中

谢谢

这是你的循环的建议,因此轮换选择数组中最接近的数字:

            randomNumber = .random(in: numbers.min()!...numbers.max()!)
            let differences = numbers.compactMap { abs([=10=] - randomNumber) }.sorted { [=10=] <  }
            let closest = randomNumber - (differences.first ?? 0)
                
            withAnimation {
            if numbers.contains(closest) {
                    rotation = closest
                } else {
                    rotation = randomNumber + (differences.first ?? 0)
                }
            }

只要记住使用正确的类型(Int、CGFloat…)。