SwiftUI Map iOS 14 手柄拖动和放大手势

Posted

技术标签:

【中文标题】SwiftUI Map iOS 14 手柄拖动和放大手势【英文标题】:SwifUI Map iOS 14 handle drag and Magnification Gesture 【发布时间】:2021-08-16 10:25:48 【问题描述】:

如果用户拖动或缩放地图,我会在地图顶部放置一个小视图,我使用下面的代码来执行此操作,但缩放事件未触发。请帮助我我所缺少的

    let drag = DragGesture()
        .onChanged( _ in
            self.onDragEnded()
        )
    let pinch = MagnificationGesture()
        .onChanged( _ in
            self.onDragEnded()
        )
    @State private var show = false

    let combinedGesture = pinch.simultaneously(with: drag)

   var body: some View 

    ZStack 
        Map(coordinateRegion: $region, showsUserLocation: true, annotationItems: results)  dest in
            
        .gesture(combinedGesture)
        if show 
            Color.green
                .frame(width: 100, height: 100, alignment: .center)
        
      
    
    private func onDragEnded() 
        show = true
        
    

【问题讨论】:

【参考方案1】:

当用户拖动和/或缩放地图时,region 会发生变化。你只需要观察MKCoordinateRegion,或者它的两个属性之一(跨度或中心):

.onChange(of: region.span) _ in
     print("regionDidChange")

您使用onChange 观察到的属性必须是Equatable

extension MKCoordinateSpan: Equatable 
    public static func == (lhs: MKCoordinateSpan, rhs: MKCoordinateSpan) -> Bool 
        lhs.latitudeDelta == rhs.latitudeDelta && lhs.longitudeDelta == rhs.longitudeDelta
    


编辑:

但是如果你想在位置变化和缩放变化时执行不同的动作,那就更复杂了。因为 1- 缩放级别取决于位置和跨度。 2-当用户放大或缩小时,中心会发生变化(非常轻微) 3-当中心改变时跨度改变(一点)

你可以这样开始:

struct MapView: View 
    @State private var region = MKCoordinateRegion(center: .init(latitude: 42, longitude: 1.2), span: .init(latitudeDelta: 10, longitudeDelta: 10))
    @State private var drag: Int = 0
    @State private var pinch: Int = 0
    @State private var oldZoomLevel: Double?
    
    var body: some View 
        ZStack(alignment: Alignment(horizontal: .center, vertical: .top)) 
            
            GeometryReader  proxy in
                Map(coordinateRegion: $region)
                    .onChange(of: region)  newRegion in
                        let zlevel = getZoomLevel(mapWidth: Double(proxy.size.width))
                        if zlevel != oldZoomLevel 
                            pinch += 1
                         else 
                            drag += 1
                        
                        oldZoomLevel = zlevel
                    
            
   
            HStack 
                Text(drag.description)
                    .padding()
                    .background(Color.pink)
                Spacer()
                Text(pinch.description)
                    .padding()
                    .background(Color.yellow)
            
        
    
    
    func getZoomLevel(mapWidth: Double) -> Double 
        let MERCATOR_RADIUS = 85445659.44705395
        let level = 20.00 - log2(region.span.longitudeDelta * MERCATOR_RADIUS * Double.pi / (180.0 * mapWidth))
        return round(level * 100000)/100000
    


还有扩展:

extension CLLocationCoordinate2D: Equatable 
    public static func == (lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool 
        lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude
    


extension MKCoordinateSpan: Equatable 
    public static func == (lhs: MKCoordinateSpan, rhs: MKCoordinateSpan) -> Bool 
        lhs.latitudeDelta == rhs.latitudeDelta && lhs.longitudeDelta == rhs.longitudeDelta
    


extension MKCoordinateRegion: Equatable 
    public static func == (lhs: MKCoordinateRegion, rhs: MKCoordinateRegion) -> Bool 
        lhs.center == rhs.center && lhs.span == rhs.span
    

【讨论】:

感谢您的详细解释,缩放和拖动这两个手势我正在做一些动作 2. 我试图观察区域变化,但是当我第一次尝试加载地图时会触发,我想要使用手指对显式用户拖动或缩放执行操作

以上是关于SwiftUI Map iOS 14 手柄拖动和放大手势的主要内容,如果未能解决你的问题,请参考以下文章

拖动 UIButton 时移动拖动手柄

如何将子元素以外的元素用作拖动手柄?

如何实现 TinyMCE 表格拖动手柄?

当我拖动自动填充手柄时,UDF 无法按预期工作

SwiftUI:滚动视图中的顶部锚定可调整大小视图

iOS 抓取器拖动句柄是 UIKit 组件吗?