簡體   English   中英

SwiftUI 拖動手勢沒有結束

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM