为什么我的 SwiftUI 旋钮会跳动而不是平滑旋转?

问题描述 投票:0回答:1

我正在尝试创建一个 SwiftUI 视图,其中有一个红色旋钮,可以围绕蓝色矩形平滑旋转。我已经实现了下面的代码,但旋钮似乎在跳跃,而不是像旋钮那样平滑旋转:



import SwiftUI

struct RotatingKnobView: View {
    @State private var knobRotation: Double = 0.0

    var body: some View {
        ZStack {
            Rectangle()
                .frame(width: 200, height: 100)
                .foregroundColor(Color.blue)
            
            Circle()
                .frame(width: 40, height: 40)
                .foregroundColor(Color.red)
                .offset(x: 100, y: 50)
                .gesture(
                    DragGesture()
                        .onChanged { value in
                            DispatchQueue.main.async {
                                withAnimation {
                                    let translation = value.translation.width
                                    let degrees = translation / 2 // Adjust sensitivity as needed
                                    
                                    // Update the rotation angle state in degrees
                                    if degrees < 0 {
                                        knobRotation = degrees * -1
                                    } else {
                                        knobRotation = degrees
                                    }
                                    
                                    print(knobRotation)
                                }
                            }
                        }
                )
        }
        .rotationEffect(Angle(degrees: knobRotation))
    }
}

struct RotatingKnobView_Previews: PreviewProvider {
    static var previews: some View {
        RotatingKnobView()
    }
}

什么可能导致此行为,以及如何使旋钮围绕矩形平滑旋转?

swift swiftui draggable draggesture
1个回答
0
投票

你的示例肯定运行不顺畅,当我在模拟器中运行它时它崩溃了😢

您似乎正在近似计算角度,因此它的跳跃也许并不奇怪。要精确计算,请参阅 SwiftUI - 拖动时抓取圆的角度

使用该帖子中的解决方案(这是我的答案),这是对您的代码的修改,可以更顺利地工作。我认为拖动手势需要应用于整个形状,而不仅仅是圆形。同样重要的是:必须在旋转效果之后应用手势!

struct RotatingKnobView: View { @State private var knobRotation: Double = 0.0 private func location2Degrees(location: CGPoint, midX: CGFloat, midY: CGFloat) -> CGFloat { let radians = location.y < midY ? atan2(location.x - midX, midY - location.y) : .pi - atan2(location.x - midX, location.y - midY) let degrees = radians * 180 / .pi return degrees < 0 ? degrees + 360 : degrees } private func applyRotation(width: CGFloat, height: CGFloat) -> some Gesture { DragGesture() .onChanged { value in let midX = width / 2 let midY = height / 2 let startAngle = location2Degrees(location: value.startLocation, midX: midX, midY: midY) let endAngle = location2Degrees(location: value.location, midX: midX, midY: midY) let dAngle = endAngle - startAngle // print(dAngle) knobRotation = dAngle } } var body: some View { Rectangle() .frame(width: 200, height: 100) .foregroundColor(Color.blue) .overlay(alignment: .bottomTrailing) { Circle() .frame(width: 40, height: 40) .foregroundColor(Color.red) .offset(x: 20, y: 20) } .rotationEffect(Angle(degrees: knobRotation)) .gesture(applyRotation(width: 200, height: 100)) } }
    
© www.soinside.com 2019 - 2024. All rights reserved.