SwiftUI:路径的coordinateSpace

时间:2019-07-13 00:47:42

标签: ios swift ipad ios-simulator swiftui

所以我有以下代码:

import SwiftUI

struct ContentView : View {
    @State private var draggingLocation = CGPoint.zero
    @State private var startLocation = CGPoint.zero
    @State private var dragging = false

    var body: some View {
        let GR = DragGesture(minimumDistance: 10, coordinateSpace: .global)
            .onEnded { value in
                self.dragging = false
                self.draggingLocation = CGPoint.zero
                self.startLocation = CGPoint.zero
            }
            .onChanged { value in
                if !self.dragging {
                    self.dragging = true
                }
                if self.startLocation == CGPoint.zero {
                    self.startLocation = value.startLocation
                }
                self.draggingLocation = value.location
            }

        return ZStack {
            if self.dragging {
                Path { path in
                    path.move(to: CGPoint(x: self.startLocation.x-5, y: self.startLocation.y-5))
                    path.addLine(to: CGPoint(x: self.draggingLocation.x-5, y: self.draggingLocation.y+5))
                    path.addLine(to: CGPoint(x: self.draggingLocation.x+5, y: self.draggingLocation.y-5))
                    path.addLine(to: CGPoint(x: self.startLocation.x+5, y: self.startLocation.y+5))
                }
                .fill(Color.black)
            }

            Circle()
            .fill(self.dragging ? Color.blue : Color.red)
            .frame(width: 100, height: 100)
            .gesture(GR)
            .offset(
                x: 75,
                y: 75
            )

            Circle()
            .fill(self.dragging ? Color.blue : Color.red)
            .frame(width: 100, height: 100)
            .gesture(GR)
            .offset(
                x: -75,
                y: -75
            )
        }
        .frame(width: 400, height: 400)
        .background(Color.gray)
    }
}

#if DEBUG
struct ContentView_Previews : PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

这会导致以下行为:

ios

我希望能够将边缘从一个圆中拖出到另一个圆中,当然问题是Path的坐标空间是相对于灰色框({{1} }),而不是全局的。 ContentView在文档中具有属性Path,但是几乎没有使用信息,因此将术语与SwiftUI进行谷歌搜索实际上会返回三个结果,所有这些实际上只是与Apple当前稀疏文档的链接。有人对如何最好地解决这个问题有想法吗?

1 个答案:

答案 0 :(得分:3)

坐标空间有三种风格:.local,.global和.named。前两个很明显。第三个命名坐标空间在像您这样的情况下非常有用。与GeometryReader结合使用时,它们也很有用。有关更多详情,请检查https://swiftui-lab.com/geometryreader-to-the-rescue/

命名坐标空间使您可以在一个视图的坐标空间中表达另一个视图的坐标。为此,SwiftUI允许您为视图的坐标空间指定名称。然后,在代码的其他地方,可以对其进行引用。在您的示例中,命名ZStack的坐标是正确的方法。

这是重构后的代码:

注意:我将路径移到下面,只是这样它才在圆圈的前面绘制。另外,请注意第一个路径,该路径仅用于防止我认为的ZStack错误。

enter image description here

import SwiftUI

struct ContentView : View {
    @State private var draggingLocation = CGPoint.zero
    @State private var startLocation = CGPoint.zero
    @State private var dragging = false

    var body: some View {
        let GR = DragGesture(minimumDistance: 10, coordinateSpace: .named("myCoordinateSpace"))
            .onEnded { value in
                self.dragging = false
                self.draggingLocation = CGPoint.zero
                self.startLocation = CGPoint.zero
        }
        .onChanged { value in
            if !self.dragging {
                self.dragging = true
            }

            if self.startLocation == CGPoint.zero {
                self.startLocation = value.startLocation
            }
            self.draggingLocation = value.location
        }

        return ZStack(alignment: .topLeading) {

            Circle()
                .fill(self.dragging ? Color.blue : Color.red)
                .frame(width: 100, height: 100)
                .overlay(Text("Circle 1"))
                .gesture(GR)
                .offset(x: 75, y: 75)

            Circle()
                .fill(self.dragging ? Color.blue : Color.red)
                .frame(width: 100, height: 100)
                .overlay(Text("Circle 2"))
                .gesture(GR)
                .offset(x: 200, y: 200)

            if self.dragging {
                Path { path in
                    path.move(to: CGPoint(x: self.startLocation.x-5, y: self.startLocation.y-5))
                    path.addLine(to: CGPoint(x: self.draggingLocation.x-5, y: self.draggingLocation.y+5))
                    path.addLine(to: CGPoint(x: self.draggingLocation.x+5, y: self.draggingLocation.y-5))
                    path.addLine(to: CGPoint(x: self.startLocation.x+5, y: self.startLocation.y+5))
                }
                .fill(Color.black)
            }

        }
        .coordinateSpace(name: "myCoordinateSpace")
        .frame(width: 400, height: 400, alignment: .topLeading)
        .background(Color.gray)
    }
}