使用拖动手势向后旋转视图
Rotation of view goes backwards with drag gesture
我有一个观点,我希望能够拖来拖去——有点像一个非自由旋转的命运之轮。拖动在 y 轴和滚轮底部工作正常,但对于 x - 拖动滚轮顶部时视图旋转方向错误。
我很确定这只需要一点额外的逻辑 - 但我尝试过的一切都不起作用 - 例如检查是否 v.startLocation.x < v.location.x
.
import SwiftUI
struct SpinningSelectorWheel: View {
var numberOfSegments: Int = 5
private var colorArray:[Color] = [.red, .green, .blue, .yellow, .brown, .gray, .purple, .red, .green, .blue, .yellow, .brown, .gray, .purple]
@State private var angle: CGFloat = 0
@State private var lastAngle: CGFloat = 0
@State private var length : CGFloat = 400
@State private var gtheta: CGFloat = 0
@State private var gstartx: CGFloat = 0
@State private var gstarty: CGFloat = 0
var body: some View {
GeometryReader
{ fullsize in
//Text("\(angle)")
VStack
{
Text("\(gtheta)")
Text("\(gstartx)")
Text("\(gstarty)")
Text("\(length)")
}
ForEach((1...numberOfSegments).reversed(), id: \.self)
{segment in
Path { path in
path.move(to: CGPoint(x: fullsize.size.width/2, y: fullsize.size.height/2))
path.addArc(center: .init(x: fullsize.size.width/2, y: fullsize.size.height/2), radius: 150, startAngle: Angle(degrees: Double(1-segment) * Double(360/numberOfSegments)), endAngle: Angle(degrees: Double(360/numberOfSegments)), clockwise: false)
}
.fill(colorArray[segment-1])
}
.rotationEffect(.degrees(Double(self.angle))).gesture(DragGesture().onChanged
{ v in
var theta = (atan2(v.location.x - self.length / 2, self.length / 2 - v.location.y) - atan2(v.startLocation.x - self.length / 2, self.length / 2 - v.startLocation.y)) * 180 / .pi
gtheta = theta
gstartx = v.startLocation.x
gstarty = v.startLocation.y
if (theta < 0) { theta += 360}
self.angle = theta + self.lastAngle
}
.onEnded { v in
self.lastAngle = self.angle
}
)
}
}
}
我为 UIKit 写的东西可能适用于 SwiftUI :
// rotation from point lPrevPoint to lTouchPoint
let lDeltaDirectionX = Double((lTouchPoint.x - lPrevPoint.x) / 2.0)
let lDeltaDirectionY = Double((lTouchPoint.y - lPrevPoint.y) / 2.0)
// only do 1 direction at a time ( the one with biggest change)
// then you check in which part of the screen you are :
if abs(lDeltaDirectionX) > abs(lDeltaDirectionY) {
if lPrevPoint.y > self.frame.size.height / 2.0 {
orientation = fmod(orientation-lDeltaDirectionX + 360.0, 360.0)
} else {
orientation = fmod(orientation+lDeltaDirectionX + 360.0, 360.0)
}
}
else
{
if lPrevPoint.x > self.frame.size.width / 2.0 {
orientation = fmod(orientation+lDeltaDirectionY + 360.0, 360.0)
} else {
orientation = fmod(orientation-lDeltaDirectionY + 360.0, 360.0)
}
}
orientation 是旋转的角度。不完美,因为它没有考虑到视图中心的距离以获得更准确的值。但可以是一个好的开始。
我有一个观点,我希望能够拖来拖去——有点像一个非自由旋转的命运之轮。拖动在 y 轴和滚轮底部工作正常,但对于 x - 拖动滚轮顶部时视图旋转方向错误。
我很确定这只需要一点额外的逻辑 - 但我尝试过的一切都不起作用 - 例如检查是否 v.startLocation.x < v.location.x
.
import SwiftUI
struct SpinningSelectorWheel: View {
var numberOfSegments: Int = 5
private var colorArray:[Color] = [.red, .green, .blue, .yellow, .brown, .gray, .purple, .red, .green, .blue, .yellow, .brown, .gray, .purple]
@State private var angle: CGFloat = 0
@State private var lastAngle: CGFloat = 0
@State private var length : CGFloat = 400
@State private var gtheta: CGFloat = 0
@State private var gstartx: CGFloat = 0
@State private var gstarty: CGFloat = 0
var body: some View {
GeometryReader
{ fullsize in
//Text("\(angle)")
VStack
{
Text("\(gtheta)")
Text("\(gstartx)")
Text("\(gstarty)")
Text("\(length)")
}
ForEach((1...numberOfSegments).reversed(), id: \.self)
{segment in
Path { path in
path.move(to: CGPoint(x: fullsize.size.width/2, y: fullsize.size.height/2))
path.addArc(center: .init(x: fullsize.size.width/2, y: fullsize.size.height/2), radius: 150, startAngle: Angle(degrees: Double(1-segment) * Double(360/numberOfSegments)), endAngle: Angle(degrees: Double(360/numberOfSegments)), clockwise: false)
}
.fill(colorArray[segment-1])
}
.rotationEffect(.degrees(Double(self.angle))).gesture(DragGesture().onChanged
{ v in
var theta = (atan2(v.location.x - self.length / 2, self.length / 2 - v.location.y) - atan2(v.startLocation.x - self.length / 2, self.length / 2 - v.startLocation.y)) * 180 / .pi
gtheta = theta
gstartx = v.startLocation.x
gstarty = v.startLocation.y
if (theta < 0) { theta += 360}
self.angle = theta + self.lastAngle
}
.onEnded { v in
self.lastAngle = self.angle
}
)
}
}
}
我为 UIKit 写的东西可能适用于 SwiftUI :
// rotation from point lPrevPoint to lTouchPoint
let lDeltaDirectionX = Double((lTouchPoint.x - lPrevPoint.x) / 2.0)
let lDeltaDirectionY = Double((lTouchPoint.y - lPrevPoint.y) / 2.0)
// only do 1 direction at a time ( the one with biggest change)
// then you check in which part of the screen you are :
if abs(lDeltaDirectionX) > abs(lDeltaDirectionY) {
if lPrevPoint.y > self.frame.size.height / 2.0 {
orientation = fmod(orientation-lDeltaDirectionX + 360.0, 360.0)
} else {
orientation = fmod(orientation+lDeltaDirectionX + 360.0, 360.0)
}
}
else
{
if lPrevPoint.x > self.frame.size.width / 2.0 {
orientation = fmod(orientation+lDeltaDirectionY + 360.0, 360.0)
} else {
orientation = fmod(orientation-lDeltaDirectionY + 360.0, 360.0)
}
}
orientation 是旋转的角度。不完美,因为它没有考虑到视图中心的距离以获得更准确的值。但可以是一个好的开始。