繁体   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