如何在Swift中同时实现三个手势?

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

我正在构建 SwiftUI 应用程序,我需要在视图中旋转、放置签名并调整其大小。我已经实现了最后两个手势,但是当我激活最后一个手势时,它破坏了一切。理想的情况是黑圈能够同时配置角度和大小,但两者开始相互冲突。在此测试片段中,我选择了使用的代码并删除了连接到签名后面的图像的代码,因为它并不重要。

主要问题是如何让

.simultaneousGesture(applyRotation(width: width, height: height))
正常工作。

struct NEwVIew: View {
    
    @State private var location: CGPoint = CGPoint(x: 150, y: 300)
    @GestureState private var fingerLocation: CGPoint? = nil
    @GestureState private var startLocation: CGPoint? = nil
    
    // Initialise to a size proportional to the screen dimensions.
    @State private var width: CGFloat = 100
    @State private var height: CGFloat = 100
    
    @State private var previousRotation: Double = 0.0
    @State private var knobRotation: Double = 0.0
    
    @State var rotationActive = false
    
    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) - 135
        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
                knobRotation = previousRotation + dAngle
                
            }
            .onEnded { value in
                previousRotation = knobRotation
            }
    }
    
    var simpleDrag: some Gesture {
        DragGesture()
            .onChanged { value in
                var newLocation = startLocation ?? location // 3
                newLocation.x += value.translation.width
                newLocation.y += value.translation.height
                self.location = newLocation
            }.updating($startLocation) { (value, startLocation, transaction) in
                startLocation = startLocation ?? location // 2
            }
    }
    
    var fingerDrag: some Gesture {
        DragGesture()
            .updating($fingerLocation) { (value, fingerLocation, transaction) in
                fingerLocation = value.location
            }
    }
    
    var body: some View {
        VStack {
            GeometryReader { geometry in
                
                ZStack {
                    
                    VStack {
                        ZStack {
                            if let image = loadImageFromDocumentDirectory(filename: "signature.png") {
                                
                                ZStack(alignment: .bottomTrailing) {
                                    
                                    Rectangle()
                                        .stroke(style: StrokeStyle(lineWidth: 1, dash: [5]))
                                        .fill(.blue)
                                        .frame(width: width, height: height)
                                    

                            // I've commented it because you don't have this image in app files.
                                    // Image(uiImage: image)
                                    // .resizable()
                                    // .scaledToFit()
                                    // .frame(width: width, height: height)
                                    // BLACK CIRCLE I WAS TALKING ABOUT
                                    Circle()
                                        .frame(width: 25, height: 25)
                                        .gesture(
                                            DragGesture()
                                                .onChanged { value in
                                                    // Enforce minimum dimensions.
                                                    DispatchQueue.main.async {
                                                        withAnimation {
                                                            
                                                            width = max(50, width + value.translation.width / 10)
                                                            height = width
                                                            
                                                        }
                                                    }
                                                }
                                        )
                                        .zIndex(1)
                                    
                                }
                                .rotationEffect(Angle(degrees: knobRotation))
                                // NEEDS TO WORK TOO AT THE SAME TIME WITH TWO FIRST!
                                //                                .simultaneousGesture(applyRotation(width: width, height: height))
                                
                            }
                            
                        }
                    }
                    .frame(maxWidth: width, maxHeight: height, alignment: .center)
                    .position(location)
                    .gesture(
                        simpleDrag.simultaneously(with: fingerDrag)
                    )
                }
                .frame(width: geometry.size.width, height: geometry.size.height)
            }
            
        }
        .background(Color.black.opacity(0.3))
        .overlay(
            VStack {
                Spacer()
                Button {
                    
                } label: {
                    Text("Save")
                }
            }
        )
        .ignoresSafeArea(.all)
    }
    
    
    func loadImageFromDocumentDirectory(filename: String) -> UIImage? {
        let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let fileURL = documentsDirectory.appendingPathComponent(filename)
        
        do {
            let imageData = try Data(contentsOf: fileURL)
            return UIImage(data: imageData)
        } catch {
            print("Error loading image: \(error)")
            return nil
        }
    }
}

ios swift swiftui gesture
© www.soinside.com 2019 - 2024. All rights reserved.