[英]SwiftUI Drag gesture is not ending
我試圖在SwiftUI中創建一個具有旋轉效果的自定義視圖。 我沒有使用旋轉手勢,而是嘗試使用拖動手勢通過向父級添加單獨的視圖來旋轉父級。 拖動子項(藍點)將旋轉其父項(ZStack)。 但是我在拖動藍點時遇到了困難。 拖動手勢沒有結束。 你們能幫我找出我做錯了什么嗎?
import SwiftUI
struct EditingHolder: View {
/* For Rotation Circle Drag */
@State private var currDragRect : CGSize = .zero
@State private var prevDragRect : CGSize = .zero
var rectRadius : CGFloat {
let sum : CGFloat = 2*pow(150, 2)
return sqrt(sum/4)
}
var dragRadius : CGFloat {
let height = prevDragRect.height + currDragRect.height
let width = prevDragRect.width + currDragRect.width
let sum = pow(height, 2) + pow(width, 2)
return sqrt(sum/4)
}
var rotateAngle : CGFloat{
let angle = asin(dragRadius/rectRadius)
print("🍄 Angle Produced = ", angle)
return angle
}
var body: some View {
/* **** Gestures **** */
let rotateDrag = DragGesture()
.onChanged({ value in
print("🏵 Rotate Circle Drag Started ...")
currDragRect = value.translation
}).onEnded({ _ in
print("🏵 Rotate Circle Drag Ended ✅")
prevDragRect.height += currDragRect.height
prevDragRect.width += currDragRect.width
currDragRect = .zero
})
//************* Views *******************
GeometryReader { geo in
ZStack(alignment: .center) {
Rectangle()
.padding()
.foregroundColor(Color.yellow)
///Rotate Circle `top`
Circle()
.foregroundColor(Color.blue)
.frame(width: 20, height: 20)
.position(x: 150 - 3, y: 3)
.gesture(rotateDrag)
}.frame(width:150, height: 150, alignment: .center)
.border(.green, width: 3)
.position(x: geo.size.width/2, y: geo.size.height/2)
.rotationEffect(.radians(rotateAngle))
}
//************* Views *******************
}
}
struct EditingHolder_Previews: PreviewProvider {
static var previews: some View {
EditingHolder()
}
}
要為特定手勢提供高優先級,有一個名為.highPriorityGesture()
的修飾符。 看看這里以獲得更好的解釋如何在 SwiftUI 中使用手勢。
我已經更新了角度計算,
/* **** Gestures **** */
let rotateDrag = DragGesture()
.onChanged({ value in
print("🏵 Rotate Circle Drag Started ...")
let difY = center.y - value.location.y
let difX = center.x - value.location.x
//Initial Angle when the drag started..
if deltaAngle == 0{
deltaAngle = atan2(difY, difX)
}else{
angle = atan2(difY, difX) - deltaAngle
}
}).onEnded({ _ in
print("🏵 Rotate Circle Drag Ended ✅")
withAnimation {
angle = 0
deltaAngle = 0
}
})
//************* Views *******************
現在將.highPriorityGesture(rotateDrag)
添加到ZStack
。
添加.onTapGesture()
以獲取角度計算的center
。 點擊視圖,然后通過拖動藍點進行旋轉。 這是最終的實現,
struct EditingHolder: View {
/* For Rotation Circle Drag */
@State private var center : CGPoint = .zero
@State private var angle : CGFloat = 0
@State private var deltaAngle : CGFloat = 0
var body: some View {
/* **** Gestures **** */
let rotateDrag = DragGesture()
.onChanged({ value in
print("🏵 Rotate Circle Drag Started ...")
let difY = center.y - value.location.y
let difX = center.x - value.location.x
//Initial Angle when the drag started..
if deltaAngle == 0{
deltaAngle = atan2(difY, difX)
}else{
angle = atan2(difY, difX) - deltaAngle
}
}).onEnded({ _ in
print("🏵 Rotate Circle Drag Ended ✅")
withAnimation {
angle = 0
deltaAngle = 0
}
})
//************* Views *******************
GeometryReader { geo in
ZStack(alignment: .center) {
Rectangle()
.padding()
.foregroundColor(Color.yellow)
///Rotate Circle `top`
Circle()
.foregroundColor(Color.blue)
.frame(width: 20, height: 20)
.position(x: 150 - 3, y: 3)
.gesture(rotateDrag)
}.frame(width:150, height: 150, alignment: .center)
.border(.green, width: 3)
.position(x: geo.size.width/2, y: geo.size.height/2)
.rotationEffect(Angle(radians: angle))
/* You have make the gesture a high priority */
.highPriorityGesture(rotateDrag)
.onTapGesture {
print("☘️ Center assigned..")
center = CGPoint(x: geo.frame(in: .global).size.width/2, y: geo.frame(in: .global).size.height/2)
}
}
//************* Views *******************
}
}
struct EditingHolder_Previews: PreviewProvider {
static var previews: some View {
EditingHolder()
}
}
拖動手勢和旋轉的順序很重要,否則 SwiftUI 會丟失被拖動視圖的上下文(通過拖動而變化)。
你也不需要 GeometryReader。 這是一個關於拖動的例子,角度計算需要更多的工作。
struct ContentView: View {
/* For Rotation Circle Drag */
@State private var currDragRect : CGSize = .zero
@State private var prevDragRect : CGSize = .zero
let rectRadius : CGFloat = 75
var dragRadius : CGFloat {
let height = prevDragRect.height + currDragRect.height
let width = prevDragRect.width + currDragRect.width
let sum = pow(height, 2) + pow(width, 2)
return sqrt(sum/4)
}
var rotateAngle : CGFloat{
let x = min(1, max(-1, dragRadius/rectRadius)) // asin only defined in -1...1
let angle = asin(x)
print("🍄 Angle Produced = ", angle)
return angle
}
var body: some View {
/* **** Gestures **** */
let rotateDrag = DragGesture()
.onChanged { value in
print("🏵 Rotate Circle Drag Started ...")
currDragRect = value.translation
}
.onEnded { _ in
print("🏵 Rotate Circle Drag Ended ✅")
prevDragRect.height += currDragRect.height
prevDragRect.width += currDragRect.width
currDragRect = .zero
}
//************* Views *******************
ZStack(alignment: .topTrailing) {
Rectangle()
.padding()
.foregroundColor(Color.yellow)
.border(.green, width: 3)
///Rotate Circle `top`
Circle()
.foregroundColor(Color.blue)
.frame(width: 20, height: 20)
.offset(x: 8, y: -8)
}
.rotationEffect(.radians(rotateAngle)) // rotation here
.gesture(rotateDrag) // drag here
.frame(width:150, height: 150, alignment: .center)
//************* Views *******************
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.