简体   繁体   English

SwiftUI Map:如何将屏幕坐标转换为map坐标?

[英]SwiftUI Map: How to convert screen coordinates to map coordinates?

Setup:设置:

I am converting an app to SwiftUI. This app had an MKMapView with annotations that could be dragged on the map.我正在将一个应用程序转换为 SwiftUI。这个应用程序有一个带有注释的MKMapView ,可以在 map 上拖动。
I was able to write a first version of the SwiftUI app with a draggable image.我能够编写带有可拖动图像的 SwiftUI 应用程序的第一个版本。
It uses a View that is displayed as annotation on the map:它使用在 map 上显示为注释的View

struct AnnotationView: View {
    var buyLocationNameBeforeDragging: String
    @State private var isDragging = false
    @GestureState var dragAmount = CGSize.zero
    var region: MKCoordinateRegion
    
    func coordinateFrom(region: MKCoordinateRegion, dragAmount: CGSize) -> CLLocationCoordinate2D {
        let coordinate = CLLocationCoordinate2D() // How to compute this?
        return coordinate
    }
    
    var drag: some Gesture {
        DragGesture()
            .onChanged { _ in
                self.isDragging = true
            }
            .onEnded { _ in
                self.isDragging = false
                let coreDataManager = testOrPreview ? CoreDataManager.test : CoreDataManager.shared
                let newCoordinate = coordinateFrom(region: region, dragAmount: dragAmount)
                // Move the dragged place to the new coordinate
                // …
            }
            .updating($dragAmount) { value, state, transaction in
                state = value.translation
            }
    }
    
    var body: some View {
        Image("PinRed")
            .offset(dragAmount)
            .defersSystemGestures(on: .all)
            .onTapGesture {
                print("tapped")
            }
            .gesture(drag)
    }
}  

It is possible to tap the annotation pin, and - after tapping longer - to drag the pin to a new location.可以点击注释图钉,并且 - 在点击更长时间后 - 将图钉拖动到新位置。

Problem:问题:

To update my model, I need the endpoint coordinates of the drag on the map. These should be computed in func coordinateFrom (see above), but I have no idea how to do this.要更新我的 model,我需要 map 上拖动的端点坐标。这些应该在func coordinateFrom中计算(见上文),但我不知道如何执行此操作。
MKMapView has eg a function convert(_:toCoordinateFrom:) , but SwiftUI's Map has nothing like this. MKMapView有一个 function convert(_:toCoordinateFrom:) ,但是 SwiftUI 的Map没有这样的东西。

Question:题:

How to do the conversion?如何进行转换?

Problem solved.问题解决了。
I 1st converted var drag: some Gesture to a function:我第一次转换var drag: some Gesture到 function:

func drag(geo: GeometryProxy) -> some Gesture {
    DragGesture(coordinateSpace: .named("screen"))
        .onChanged { value in
            self.isDragging = true
        }
        .onEnded { _ in
            self.isDragging = false
            let coreDataManager = testOrPreview ? CoreDataManager.test : CoreDataManager.shared
            let newCoordinate = coordinateFrom(region: region, geo: geo, dragAmount: dragAmount)
            // Move the dragged place to the new coordinate
            // …
        }
        .updating($dragAmount) { value, state, transaction in
            state = value.translation
        }
}

where geo is supplied by the body of the AnnotationView , and .coordinateSpace(name: "screen") has been applied to the view displaying the map:其中geoAnnotationView的主体提供,并且.coordinateSpace(name: "screen")已应用于显示 map 的视图:

var body: some View {
    GeometryReader { geo in
        Image("PinRed")
            .offset(dragAmount)
            .defersSystemGestures(on: .all)
            .onTapGesture {
                print("Global center: \(geo.frame(in: .global).midX) x \(geo.frame(in: .global).midY)")
            }
            .gesture(drag(geo: geo))
    }
    .frame(width: 40, height: 30)
}

Next, I converted the map coordinates from screen coordinates to map coordinates using the old MKMapView as:接下来,我使用旧的MKMapView将 map 坐标从屏幕坐标转换为 map 坐标:

func coordinateFrom(region: MKCoordinateRegion, geo: GeometryProxy, dragAmount: CGSize) -> CLLocationCoordinate2D {
    let mkMapView = MKMapView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height))
    mkMapView.region = region
    let frame = geo.frame(in: .global)
    let dragEndPoint = CGPoint(x: frame.origin.x + dragAmount.width, y: frame.origin.y + dragAmount.height)
    let dragEndCFoordinate = mkMapView.convert(dragEndPoint, toCoordinateFrom: mkMapView)
    return dragEndCFoordinate
}

Here, I assume the MKMapView and SwiftUI Map use the same coordinate transforms.在这里,我假设MKMapView和 SwiftUI Map使用相同的坐标变换。 In my case, I don't see any differences.就我而言,我没有看到任何差异。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM