Ver Fonte

fix:地图添加方向标签箭头。

“HeShaoZe” há 4 meses atrás
pai
commit
8c901991c6

+ 112 - 0
plugins/map_mapkit_ios/ios/Classes/MapView/ArrowPolylineRenderer.swift

@@ -0,0 +1,112 @@
+//
+//  ArrowPolylineRenderer.swift
+//  map_mapkit_ios
+//
+//  Created by 诺诺诺的言 on 2025/7/14.
+//
+
+import UIKit
+import MapKit
+import Combine
+
+
+class ArrowPolylineRenderer: MKPolylineRenderer {
+    // 箭头属性
+    var arrowColor: UIColor = .red
+    var arrowSize: CGFloat = 8
+    var arrowSpacing: CGFloat = 30   // 默认值
+    
+    // 边框属性
+    var borderWidth: CGFloat = 0
+    var borderColor: UIColor = .clear
+    
+    override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
+        // 1. 绘制边框
+        if borderWidth > 0 {
+            context.saveGState()
+            // 边框宽度 = 主线条宽度 + 2倍边框宽度(左右各扩展 borderWidth)
+            let borderLineWidth = lineWidth + borderWidth * 2
+            context.setLineWidth(borderLineWidth)
+            context.setStrokeColor(borderColor.cgColor)
+            context.setLineCap(lineCap)  // 保持与主线条一致的线帽样式
+            context.setLineJoin(lineJoin) // 保持与主线条一致的拐角样式
+            // 绘制边框线条
+            super.draw(mapRect, zoomScale: zoomScale, in: context)
+            context.restoreGState()
+        }
+        
+        // 2. 绘制主轨迹线
+        super.draw(mapRect, zoomScale: zoomScale, in: context)
+        
+        // 3. 绘制箭头(数量减半)
+        drawArrows(mapRect: mapRect, zoomScale: zoomScale, in: context)
+    }
+    
+    private func drawArrows(mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
+        guard polyline.pointCount >= 2 else { return }
+        
+        let scaledArrowSize = arrowSize / zoomScale
+        let scaledArrowSpacing = arrowSpacing / zoomScale
+        
+        var distance: CGFloat = 0
+        let points = polyline.points()
+        
+        // 使用stride跳过每隔一个的箭头
+        let step = 2 // 跳过间隔
+        var arrowIndex = 0
+        
+        for i in 0..<polyline.pointCount-1 {
+            let startPoint = point(for: points[i])
+            let endPoint = point(for: points[i+1])
+            
+            let dx = endPoint.x - startPoint.x
+            let dy = endPoint.y - startPoint.y
+            let segmentLength = hypot(dx, dy)
+            
+            guard segmentLength > 2 / zoomScale else { continue }
+            
+            let arrowCount = Int(floor((distance + segmentLength) / scaledArrowSpacing))
+            
+            for j in 0..<arrowCount {
+                // 只绘制每隔step个箭头
+                if arrowIndex % step == 0 {
+                    let position = CGFloat(j) * scaledArrowSpacing - distance
+                    let ratio = position / segmentLength
+                    
+                    guard ratio >= 0 && ratio <= 1 else { continue }
+                    
+                    let arrowPoint = CGPoint(
+                        x: startPoint.x + dx * ratio,
+                        y: startPoint.y + dy * ratio
+                    )
+                    
+                    let angle = atan2(dy, dx)
+                    drawSingleArrow(at: arrowPoint, angle: angle, size: scaledArrowSize, in: context)
+                }
+                arrowIndex += 1
+            }
+            
+            distance = (distance + segmentLength).truncatingRemainder(dividingBy: scaledArrowSpacing)
+        }
+    }
+    
+    private func drawSingleArrow(at point: CGPoint, angle: CGFloat, size: CGFloat, in context: CGContext) {
+        context.saveGState()
+        context.translateBy(x: point.x, y: point.y)
+        context.rotate(by: angle)
+        
+        let arrowPath = UIBezierPath()
+        arrowPath.move(to: CGPoint(x: 3.2, y: 0))
+        arrowPath.addLine(to: CGPoint(x: 0, y: 2.6))
+        arrowPath.addLine(to: CGPoint(x: -3.2, y: 2.6))
+        arrowPath.addLine(to: CGPoint(x: 0, y: 0))
+        arrowPath.addLine(to: CGPoint(x: -3.2, y: -2.6))
+        arrowPath.addLine(to: CGPoint(x: 0, y: -2.6))
+        arrowPath.close()
+        
+        context.setFillColor(arrowColor.cgColor)
+        context.addPath(arrowPath.cgPath)
+        context.fillPath()
+        context.restoreGState()
+    }
+}

+ 35 - 5
plugins/map_mapkit_ios/ios/Classes/MapView/MapViewController.swift

@@ -72,8 +72,17 @@ class MapViewController: UIViewController {
             .receive(on: DispatchQueue.main)
             .sink { [weak self] polylines in
                 self?.mapView.removeOverlays(self?.mapView.overlays ?? [])
-                self?.mapView.addOverlays(polylines.map({ $0.polyline }))
-
+                var polyinesList = [MKPolyline]();
+                for polyline in polylines {
+                    let polylineItem : MKPolyline = polyline.polyline
+                    polylineItem.associatedLineId = polyline.id
+                    polylineItem.associatedLineType = polyline.lineType
+                    polylineItem.associatedColor = polyline.color
+                    polylineItem.associatedWidth = polyline.width
+                    polyinesList.append(polylineItem)
+                }
+                self?.mapView.addOverlays(polyinesList)
+                //self?.mapView.addOverlays(polylines.map({ $0.polyline }))
                 if let padding = polylines.last?.mapPadding {
                     self?.mapView.fitsAllPoints(
                         points: polylines.last?.points.compactMap({ MKMapPoint($0) }) ?? [],
@@ -119,12 +128,33 @@ extension MapViewController: MKMapViewDelegate {
     }
 
     func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
-        let renderer = MKPolylineRenderer(overlay: overlay)
+        
+        guard let polyline = overlay as? MKPolyline else {
+            return MKOverlayRenderer(overlay: overlay)
+        }
+        let renderer = ArrowPolylineRenderer(polyline: polyline)
         renderer.lineWidth = 6
         //rgba(123, 125, 255, 1)
-        renderer.strokeColor = UIColor(red: 123 / 255, green: 125 / 255, blue: 255 / 255, alpha: 1)
+        renderer.strokeColor = UIColor(red: 0.27, green: 0.46, blue: 1, alpha: 1)//UIColor.init(hex: "#4476FF");//UIColor(red: 123 / 255, green: 125 / 255, blue: 255 / 255, alpha: 1)
         renderer.lineCap = .round
         renderer.lineJoin = .round
+        
+        // 设置箭头样式
+        renderer.arrowColor = UIColor.white // 箭头颜色
+        renderer.arrowSize = 12      // 增大箭头大小
+        renderer.arrowSpacing = 40   // 减小箭头间距
+        renderer.borderWidth = 1
+        renderer.borderColor = UIColor(red: 0.35, green: 0.36, blue: 0.99, alpha: 1)//UIColor.hex(0x5A5DFD)
+        
+        //normal error selected color
+        if polyline.associatedLineType == "normal" {
+            renderer.strokeColor = UIColor(red: 0.27, green: 0.46, blue: 1, alpha: 1)
+        } else  if polyline.associatedLineType == "error" {
+            renderer.strokeColor = UIColor(red: 1, green: 0.43, blue: 0.43, alpha: 1)
+        } else  if polyline.associatedLineType == "selected" {
+            renderer.strokeColor = UIColor(red: 0.08, green: 0.8, blue: 0.63, alpha: 1)
+        }
         return renderer
     }
-} 
+}
+

+ 51 - 0
plugins/map_mapkit_ios/ios/Classes/MapView/Model/Models.swift

@@ -7,6 +7,7 @@
 
 import Foundation
 import MapKit
+import ObjectiveC
 
 extension Decodable {
     static func fromJson(json: Any) -> Self? {
@@ -47,6 +48,56 @@ struct ATMapPadding: Codable {
     }
 }
 
+
+// 定义关联对象的键
+private var associatedLineIdKey = "associatedLineIdKey"
+private var associatedLineTypeKey = "associatedLineTypeKey"
+private var associatedColorKey = "associatedColorKey"
+private var associatedWidthKey = "associatedWidthKey"
+
+extension MKPolyline {
+    // 关联 lineId 属性
+    var associatedLineId: String? {
+        get {
+            return objc_getAssociatedObject(self, &associatedLineIdKey) as? String
+        }
+        set {
+            objc_setAssociatedObject(self, &associatedLineIdKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+    
+    // 关联 lineType 属性
+    var associatedLineType: String? {
+        get {
+            return objc_getAssociatedObject(self, &associatedLineTypeKey) as? String
+        }
+        set {
+            objc_setAssociatedObject(self, &associatedLineTypeKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+    
+    // 关联 color 属性
+    var associatedColor: String? {
+        get {
+            return objc_getAssociatedObject(self, &associatedColorKey) as? String
+        }
+        set {
+            objc_setAssociatedObject(self, &associatedColorKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+    
+    // 关联 width 属性
+    var associatedWidth: Double? {
+        get {
+            return objc_getAssociatedObject(self, &associatedWidthKey) as? Double
+        }
+        set {
+            objc_setAssociatedObject(self, &associatedWidthKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+}
+
+
 class ATMapPolyline: NSObject, Codable {
     var id: String = UUID().uuidString
     var lineId: String         // 新增:用于记录的线ID