如何在SwiftUI地图视图中将点击手势转换为坐标? [英] How to convert tap gesture to coordinate in a SwiftUI Map view?

查看:0
本文介绍了如何在SwiftUI地图视图中将点击手势转换为坐标?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从MapKitMapAnnotation项添加到我的Map()视图。

如果您在文本字段中手动添加坐标,则一切正常,但我找不到通过点击地图来添加坐标的方法。

我在Internet上阅读了很多,但没有找到有关onTap()映射事件处理的任何信息。

到目前为止,我的地图视图是这样的:

struct MyMap : View {
    
    @State private var myRegion:MKCoordinateRegion = {
        var newRegion = MKCoordinateRegion()
        newRegion.center.latitude = 53.7576508
        newRegion.center.longitude = -11.1811597
        newRegion.span.latitudeDelta = 0.1
        newRegion.span.longitudeDelta = 0.1
        
        return newRegion
    }()
    
    
    @State private var annotationItems : [Annotation] = [
        Annotation(name: "Pin1", description: "myDescription", coordinate: CLLocationCoordinate2D(latitude: 123.7576508, longitude: -7.2373215))
    ]
    
    var body: some View {
        
        ZStack {
            Map(coordinateRegion: self.$myRegion, interactionModes: .all, annotationItems: annotationItems){ item in
                MapAnnotation(coordinate: item.coordinate){
                    PinView(pin: item)
                }
                
            }
            .edgesIgnoringSafeArea(.all)
        }
    }
}

有没有办法获取用户在地图上点击的位置的坐标?

推荐答案

执行此操作的唯一纯SwiftUI方式将阻止地图的一个或多个内置手势。

它是DragGesture和一些数学的组合,将手势的位置转换为视图和地图之间的比率,然后根据可见跨度获得坐标。

import SwiftUI
import MapKit
struct TappableMapView: View {
    @State var region: MKCoordinateRegion = .init(center: .init(latitude: 37.8199, longitude: -122.4783 ), latitudinalMeters: 500, longitudinalMeters: 500)
    @State var locations: [CLLocationCoordinate2D] = []
    @State var location: CGPoint = .zero
    var body: some View {
        VStack{
            GeometryReader{ geo in
                ZStack{
                    Map(coordinateRegion: $region, annotationItems: locations, annotationContent: {location in
                        MapAnnotation(coordinate: location){
                            Image(systemName: "circle.fill")
                                .resizable()
                                .foregroundColor(.red)
                                .frame(width: 50, height: 50, alignment: .center)
                        }
                    }) .simultaneousGesture(
                        DragGesture(minimumDistance: 0, coordinateSpace: .local).onEnded({ value in
                            location = value.location
                            //Figure out how the postion relates to the view %/ratio
                            let xPer = location.x/(geo.size.width)
                            let yPer = location.y/(geo.size.height)
                            //Multiply the span by the postion ratio
                            let lonDel = region.span.longitudeDelta * xPer
                            let latDel = region.span.latitudeDelta * yPer
                            //Get the start
                            let stLat = region.center.latitude + region.span.latitudeDelta/2
                            let stLon = region.center.longitude - region.span.longitudeDelta/2
                            //Add the span/ratio to the start
                            let loc = CLLocationCoordinate2D(latitude: stLat - latDel, longitude: stLon + lonDel)
                            locations.append(loc)
                        })
                        
                    )
                }
            }
        }
    }
}

struct TappableMapView_Previews: PreviewProvider {
    static var previews: some View {
        TappableMapView()
    }
}
它的用途非常有限,因为Map中的DragGesture被自定义的DragGesture覆盖。当翻译不是零时,您可以尝试补偿并更改region,如上面的if else所示,但它不是实时更新。

第2部分

执行此操作的另一种方法是使用地图注释模式,其中地图手势将被禁用并替换为自定义手势。

import SwiftUI
import MapKit
struct TappableMapView: View {
    @State var region: MKCoordinateRegion = .init(center: .init(latitude: 37.8199, longitude: -122.4783 ), latitudinalMeters: 500, longitudinalMeters: 500)
    @State var locations: [CLLocationCoordinate2D] = []
    @State var location: CGPoint = .zero
    @State var gestureMask: GestureMask = .subviews
    var body: some View {
        VStack{
            //Switch between gestures
            Button("(gestureMask == .subviews ? "place annotaion mode":"map gesture mode")", action: {
                gestureMask = (gestureMask == .subviews ? .gesture: .subviews)
            })
            GeometryReader{ geo in
                ZStack{
                    Map(coordinateRegion: $region, annotationItems: locations, annotationContent: {location in
                        MapAnnotation(coordinate: location){
                            Image(systemName: "circle.fill")
                                .resizable()
                                .foregroundColor(.red)
                                .frame(width: 50, height: 50, alignment: .center)
                        }
                        
                    })
                        .gesture(
                            DragGesture(minimumDistance: 0, coordinateSpace: .local)
                                .onEnded({ value in
                                    location = value.location
                                    //Figure out how the postion relates to the view %/ratio
                                    let xPer = location.x/(geo.size.width)
                                    let yPer = location.y/(geo.size.height)
                                    //Multiply the span by the postion ratio
                                    let lonDel = region.span.longitudeDelta * xPer
                                    let latDel = region.span.latitudeDelta * yPer
                                    //Get the start
                                    let stLat = region.center.latitude + region.span.latitudeDelta/2
                                    let stLon = region.center.longitude - region.span.longitudeDelta/2
                                    //Add the span/ratio to the start
                                    let loc = CLLocationCoordinate2D(latitude: stLat - latDel, longitude: stLon + lonDel)
                                        
                                        locations.append(loc)
                                })
                            , including: gestureMask)
                    //The mask is applied here
                }
            }
        }
    }
}

struct TappableMapView_Previews: PreviewProvider {
    static var previews: some View {
        TappableMapView()
    }
}

这篇关于如何在SwiftUI地图视图中将点击手势转换为坐标?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆