ios 如何在Map上拖动Map多边形

33qvvth1  于 2023-10-21  发布在  iOS
关注(0)|答案(1)|浏览(111)

我正在尝试在SwiftUIMap上拖动MapPolygon。我已经创建了这个示例代码,以显示它并没有顺利和准确地拖动MapPolygon
要在Map上平滑而准确地拖动整个MapPolygon,有什么更合适的方法?
在我看来,问题是MapPolygon(doDrag)的所有点的翻译,这不是一个好的翻译方法,但我找不到更好的方法。
(iOS-17和MacCatalyst)

struct ContentView: View {
    @State private var isDraging = false
    
    var body: some View {
        VStack {
            ToolbarView(isDraging: $isDraging)
            MapViewer(isDraging: $isDraging)
        }
    }
}

struct MapViewer: View {
    @Binding var isDraging: Bool
    @State private var modes = MapInteractionModes.all
    
    @State private var cameraPosition: MapCameraPosition = .camera(
        MapCamera(centerCoordinate: CLLocationCoordinate2D(latitude: 35.68, longitude: 139.75), distance: 4000.0, heading: 0, pitch: 0)
    )
    
    @State private var polyPoints = [CLLocationCoordinate2D(latitude: 35.682890728577135, longitude: 139.74688521853778),CLLocationCoordinate2D(latitude: 35.682457291364656, longitude: 139.7513297533676),CLLocationCoordinate2D(latitude: 35.679605242840324, longitude: 139.74859855588522)]
    
    var body: some View {
        MapReader { reader in
            Map(position: $cameraPosition, interactionModes: modes) {
                MapPolygon(coordinates: polyPoints)
                    .stroke(.white, lineWidth: 2)
                    .foregroundStyle(.purple.opacity(0.3))
            }
            .gesture(DragGesture()
                .onChanged { drag in
                    if isDraging {
                        doDrag(drag)
                    }
                }
            )
        }
        .mapStyle(.imagery)
        .mapControlVisibility(.hidden)
        .edgesIgnoringSafeArea(.all)
        .onChange(of: isDraging) {
            if isDraging { modes.subtract(.all) }
            else { modes.update(with: .all) }
        }
    }
    
    // this is not working well
    func doDrag(_ drag: DragGesture.Value) {
        for i in polyPoints.indices {
            let p = MKMapPoint(polyPoints[i])
            let newP = MKMapPoint(x: p.x + drag.translation.width, y: p.y + drag.translation.height)
            polyPoints[i] = newP.coordinate
        }
    }
 
}

struct ToolbarView: View {
    @Binding var isDraging: Bool
    
    var body: some View {
        Button(action: { isDraging.toggle() }) {
            VStack {
                Image(systemName: "move.3d")
                    .resizable()
                    .frame(width: 25, height: 25)
                    .foregroundColor(isDraging ? .red : .blue)
                Text(isDraging ? "Drag on" : "Drag off")
                    .font(.caption)
                    .foregroundColor(isDraging ? .red : .blue)
            }.frame(width: 80, height: 60)
        }
        .buttonStyle(.bordered)
        .background(Color.white)
        .clipShape(RoundedRectangle(cornerRadius: 10))
    }
}

已尝试平移贴图多边形的所有点,但这不会给予可接受的结果。

iyzzxitl

iyzzxitl1#

我找不到一个更好的方法来做到这一点,而不是单独更新点。但正如我在评论中提到的,它工作不好的一个原因是因为你累积地应用了拖动平移。不是将拖动平移添加到起始位置,而是将其添加到当前位置。因此,只要拖动平移超过最小值,多边形就会飞出帧。
我建议这些改变:

  • 在开始拖动时捕获多边形位置,并将其用于所有更新。
  • 在拖动结束时,重置开始位置,以便为另一次拖动做好准备。
  • doDrag中,我将准备一个新数组,并在一次操作中赋值,而不是更新数组中的元素。这可能有助于触发更少的视图更新。

当我尝试这些变化时,我发现当你试图拖动它时,多边形几乎没有移动。看来,拖动偏移需要缩放的一个因素,约。25、让它工作我不知道这是否与相机高度有关,或者是否有一种方法可以找到缩放因子,而不是硬编码。如果你也不知道答案,你可以把它作为一个新问题的主题。

  • 编辑 * 通过更多的实验,我发现缩放因子可以近似计算为:(Map相机距离)/ 160。我不知道这是否在任何地方都有记录。

所以这里有一个版本,工作得更好一点:

struct MapViewer: View {
    @Binding var isDragging: Bool
    @State private var modes = MapInteractionModes.all

    @State private var cameraPosition: MapCameraPosition = .camera(
        MapCamera(centerCoordinate: CLLocationCoordinate2D(latitude: 35.68, longitude: 139.75), distance: 4000.0, heading: 0, pitch: 0)
    )

    @State private var polyPoints = [
        CLLocationCoordinate2D(latitude: 35.682890728577135, longitude: 139.74688521853778),
        CLLocationCoordinate2D(latitude: 35.682457291364656, longitude: 139.7513297533676),
        CLLocationCoordinate2D(latitude: 35.679605242840324, longitude: 139.74859855588522)
    ]

    @State private var dragPointsBegin = [CLLocationCoordinate2D]()
    let mapScalingFactor: CGFloat = 25 // where can this be obtained from?

    var body: some View {
        MapReader { reader in
            Map(position: $cameraPosition, interactionModes: modes) {
                MapPolygon(coordinates: polyPoints)
                    .stroke(.white, lineWidth: 2)
                    .foregroundStyle(.purple.opacity(0.3))
            }
            .gesture(DragGesture()
                .onChanged { drag in
                    if isDragging {
                        doDrag(drag.translation)
                    }
                }
                .onEnded { _ in

                    // Reset the start position, ready for another drag
                    dragPointsBegin = polyPoints
                }
            )
        }
        .mapStyle(.imagery)
        .mapControlVisibility(.hidden)
        .edgesIgnoringSafeArea(.all)
        .onChange(of: isDragging) {
            if isDragging {
                modes.subtract(.all)

                // Capture a snapshot of the polygon points
                dragPointsBegin = polyPoints
            }
            else { modes.update(with: .all) }
        }
    }

    func doDrag(_ translation: CGSize) {
        var draggedPoints = [CLLocationCoordinate2D]()
        draggedPoints.reserveCapacity(dragPointsBegin.count)
        for point in dragPointsBegin {
            let p = MKMapPoint(point)
            draggedPoints.append(
                MKMapPoint(
                    x: p.x + (translation.width * mapScalingFactor),
                    y: p.y + (translation.height * mapScalingFactor)
                )
                .coordinate
            )
        }
        polyPoints = draggedPoints
    }
}

如果polyPoints和/或dragPointsBeginMKMapPoint的数组,这也可能有帮助,因为这可能会减少计算开销。但是如果多边形只由少数几个点组成,我想这不会有太大的区别。

相关问题