Browse Source

add fit map padding for points

Groot 8 months ago
parent
commit
7452c471ca

+ 7 - 1
plugins/map_mapkit_ios/example/lib/main.dart

@@ -95,7 +95,13 @@ class _MyHomePageState extends State<MyHomePage> {
                       "longitude": Random().nextDouble() * (120.0 - 110.0) + 110.0
                     });
                     _methodChannel?.invokeMethod("polyline#addPolyline", {
-                      "points": points
+                      "points": points,
+                      "mapPadding": {
+                        "top": 10,
+                        "left": 10,
+                        "bottom": 600,
+                        "right": 10
+                      }
                     });
                     // start marker
                     _methodChannel?.invokeMethod("marker#updateOrAddMarkers", {

+ 68 - 0
plugins/map_mapkit_ios/ios/Classes/MapView/Extension/MapKit+E.swift

@@ -0,0 +1,68 @@
+//
+//  MapKit+E.swift
+//  Pods
+//
+//  Created by Groot on 2025/5/14.
+//
+
+import MapKit
+import Foundation
+
+extension MKMapView {
+    // 按比例 按padding适应annotation
+    public func fitsAllPoints(
+        points: [MKMapPoint],
+        padding: UIEdgeInsets,
+        aspectRatio: Double? = nil,
+        animated: Bool = true
+    ) {
+        var zoomRect: MKMapRect = .null
+        for point in points {
+            let pointRect = MKMapRect(x: point.x, y: point.y, width: 0, height: 0)
+            if zoomRect.isNull {
+                zoomRect = pointRect
+            } else {
+                zoomRect = zoomRect.union(pointRect)
+            }
+        }
+
+        // Calculate the desired size based on the aspect ratio
+        let aspectRatio = aspectRatio ?? 1.0
+        let width = zoomRect.size.width
+        let height = zoomRect.size.height
+        let desiredWidth = max(width, height * aspectRatio)
+        let desiredHeight = max(height, width / aspectRatio)
+
+        // Calculate the center of the annotations
+        let center = MKMapPoint(x: zoomRect.midX, y: zoomRect.midY)
+
+        // Create a new MKMapRect with the desired aspect ratio and centered on the annotations
+        let newMapRect = MKMapRect(
+            x: center.x - desiredWidth / 2,
+            y: center.y - desiredHeight / 2,
+            width: desiredWidth,
+            height: desiredHeight
+        )
+        setVisibleMapRect(newMapRect, edgePadding: padding, animated: animated)
+    }
+
+    func calculateMapRect(points: [MKMapPoint], padding: UIEdgeInsets = .zero) -> MKMapRect {
+        var zoomRect: MKMapRect = .null
+        for point in points {
+            let pointRect = MKMapRect(x: point.x, y: point.y, width: 0, height: 0)
+            if zoomRect.isNull {
+                zoomRect = pointRect
+            } else {
+                zoomRect = zoomRect.union(pointRect)
+            }
+        }
+        return mapRectThatFits(zoomRect, edgePadding: padding)
+    }
+
+    func takeSnapShot(option: MKMapSnapshotter.Options, completion: @escaping (MKMapSnapshotter.Snapshot?) -> Void) {
+        let shotter = MKMapSnapshotter(options: option)
+        shotter.start(with: .global()) { shot, _ in
+            completion(shot)
+        }
+    }
+}

+ 9 - 1
plugins/map_mapkit_ios/ios/Classes/MapView/MapViewController.swift

@@ -71,6 +71,14 @@ class MapViewController: UIViewController {
             .sink { [weak self] polylines in
                 self?.mapView.removeOverlays(self?.mapView.overlays ?? [])
                 self?.mapView.addOverlays(polylines.map({ $0.polyline }))
+
+                if let padding = polylines.last?.mapPadding {
+                    self?.mapView.fitsAllPoints(
+                        points: polylines.last?.points.compactMap({ MKMapPoint($0) }) ?? [],
+                        padding: padding.padding,
+                        animated: true
+                    )
+                }
             }
             .store(in: &cancellables)
     }
@@ -106,4 +114,4 @@ extension MapViewController: MKMapViewDelegate {
         renderer.lineJoin = .round
         return renderer
     }
-} 
+} 

+ 36 - 2
plugins/map_mapkit_ios/ios/Classes/MapView/Model/Models.swift

@@ -33,16 +33,50 @@ struct ATMapCameraPosition: Codable {
     var zoom: CGFloat
 }
 
+struct ATMapPadding: Codable {
+    var top: CGFloat
+    var left: CGFloat
+    var bottom: CGFloat
+    var right: CGFloat
+
+    var padding: UIEdgeInsets {
+        return UIEdgeInsets(top: top, left: left, bottom: bottom, right: right)
+    }
+}
+
 class ATMapPolyline: NSObject, Codable {
     var id: String = UUID().uuidString
     var points: [CLLocationCoordinate2D]
-
+    
+    var mapPadding: ATMapPadding?
+    
     var polyline: MKPolyline {
         return MKPolyline(coordinates: points, count: points.count)
     }
 
-    init(points: [CLLocationCoordinate2D]) {
+    init(points: [CLLocationCoordinate2D], mapPadding: ATMapPadding? = nil) {
         self.points = points
+        self.mapPadding = mapPadding
+    }
+    
+    enum CodingKeys: String, CodingKey {
+        case points, mapPadding
+    }
+    
+    required init(from decoder: Decoder) throws {
+        let container = try decoder.container(keyedBy: CodingKeys.self)
+        
+        points = try container.decode([CLLocationCoordinate2D].self, forKey: .points)
+        
+        if container.contains(.mapPadding) {
+            mapPadding = try container.decodeIfPresent(ATMapPadding.self, forKey: .mapPadding)
+        }
+    }
+    
+    func encode(to encoder: Encoder) throws {
+        var container = encoder.container(keyedBy: CodingKeys.self)
+        try container.encode(points, forKey: .points)
+        try container.encodeIfPresent(mapPadding, forKey: .mapPadding)
     }
 }
 

+ 2 - 4
plugins/map_mapkit_ios/ios/Classes/MapView/ViewModel/MapViewModel.swift

@@ -96,12 +96,10 @@ class MapViewModel: NSObject, ObservableObject, MapCapability {
 
     // 处理地图添加Polyline
     func handleMapAddPolyline(args: [String: Any]?, result: @escaping FlutterResult) {
-        guard let args = args, let pointsArray = args["points"] as? [[String: Any]] else {
+        guard let args = args, let polyline = ATMapPolyline.fromJson(json: args) else {
             result(paramsDecodeError)
             return
         }
-        let coordinates = pointsArray.compactMap({ CLLocationCoordinate2D.fromJson(json: $0) })
-        let polyline = ATMapPolyline(points: coordinates)
         polylines.append(polyline)
 
         result(nil)
@@ -113,4 +111,4 @@ extension MapViewModel {
     func toggleMarkerSelected(marker: inout ATMapMarker) {
         marker.isSelected = !marker.isSelected
     }
-}
+}