// // MapAmapThemeControl.swift // map_amap_ios // // Created by 诺诺诺的言 on 2025/7/22. // import Foundation import MapKit import Combine import AMapFoundationKit import MAMapKit @available(iOS 13.0, *) class MapAmapThemeControl: UIViewController { required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } let viewModel: MapAmapViewAndDataExchange var autonaviMap : MAMapView! //let mapView = MKMapView() private var cancellables = Set() init(viewModel: MapAmapViewAndDataExchange) { self.viewModel = viewModel super.init(nibName: nil, bundle: nil) //mapView.showsUserLocation = false } override func viewDidLoad() { super.viewDidLoad() // 1. 设置隐私(必须!) MAMapView.updatePrivacyShow(.didShow, privacyInfo: .didContain) MAMapView.updatePrivacyAgree(.didAgree) AMapServices.shared().enableHTTPS = true loadMainMapView() bindViewModel() } private func loadMainMapView() { guard AMapServices.shared().apiKey != nil else { fatalError("高德地图API Key未配置!") } autonaviMap = MAMapView(frame: view.bounds) print("地图初始化失败,请检查Key和Bundle ID--\(autonaviMap)") guard let map = autonaviMap else { print("地图初始化失败,请检查Key和Bundle ID--") return } map.delegate = self map.isRotateCameraEnabled = false map.showsCompass = false map.isRotateEnabled = false map.mapType = .standard map.showsUserLocation = false map.userTrackingMode = .none view.addSubview(map) map.translatesAutoresizingMaskIntoConstraints = false view.addSubview(map) NSLayoutConstraint.activate([ map.topAnchor.constraint(equalTo: view.topAnchor), map.bottomAnchor.constraint(equalTo: view.bottomAnchor), map.leadingAnchor.constraint(equalTo: view.leadingAnchor), map.trailingAnchor.constraint(equalTo: view.trailingAnchor) ]) } private func bindViewModel() { viewModel.$markers .receive(on: DispatchQueue.main) .sink { [weak self] markers in if let annotationsList = self?.autonaviMap.annotations { print("annotationsListsdfsdfs---\(annotationsList)"); self?.autonaviMap.removeAnnotations(self?.autonaviMap.annotations) } // UIView.animate(withDuration: 0.3) { // self?.autonaviMap.addAnnotations(markers) // } var mapMarkerList = [MAPointAnnotation](); for markerItem in markers { let annotationItem : MyMAPointAnnotation = MyMAPointAnnotation(itemMarker: markerItem) annotationItem.title = markerItem.markerName; annotationItem.coordinate = markerItem.coordinate; mapMarkerList.append(annotationItem) } self?.autonaviMap.addAnnotations(mapMarkerList) // self?.autonaviMap.selectAnnotation(mapMarkerList.first, animated: true) self?.autonaviMap.setZoomLevel(20, animated: true) /*if !mapMarkerList.isEmpty { let selectIemt : MAPointAnnotation = mapMarkerList.first! self?.autonaviMap.setCenter(selectIemt.coordinate, animated: true) }*/ } .store(in: &cancellables) ///移动到特定的位置 viewModel.$currentRegion .compactMap { $0 } .receive(on: DispatchQueue.main) .sink { [weak self] region in self?.autonaviMap.setRegion(region, animated: true) //self?.mapView.setRegion(region, animated: true) } .store(in: &cancellables) viewModel.$polylines .receive(on: DispatchQueue.main) .sink { [weak self] polylines in self!.autonaviMap.removeOverlays(self!.autonaviMap.overlays) guard let self, !polylines.isEmpty else { return } // 清除旧覆盖物 self.autonaviMap.removeOverlays(self.autonaviMap.overlays) var polyinesList = [MAPolyline](); for polyline in polylines { let polylineItem : MyMAPolyline = MyMAPolyline(coordinates: &polyline.points, count: UInt(polyline.points.count)) polylineItem.itemPolyLine = polyline polyinesList.append(polylineItem) } // 添加新覆盖物 self.autonaviMap.addOverlays(polyinesList) // 自动调整视野 if let lastPolyline = polylines.last, let padding = lastPolyline.mapPadding { self.autonaviMap.showOverlays( polyinesList, edgePadding: UIEdgeInsets( top: padding.top, left: padding.left, bottom: padding.bottom, right: padding.right ), animated: true ) } /*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) }) ?? [], padding: padding.padding, animated: true ) } guard let self, !polylines.isEmpty else { return } // 清除旧覆盖物 self.autonaviMap.removeOverlays(self.autonaviMap.overlays) // 创建自定义Polyline类数组 let customPolylines = polylines.compactMap { polyline -> CustomPolyline? in // 创建高德地图Polyline let count = UInt(polyline.points.count) guard let mapPolyline = MAPolyline(coordinates: &polyline.points , count: count) else { return nil } // 使用自定义类包装 return CustomPolyline( polyline: mapPolyline, id: polyline.id, color: polyline.color, width: polyline.width ) } // 添加新覆盖物 self.autonaviMap.addOverlays(customPolylines.map { $0.polyline }) // 自动调整视野 if let lastPolyline = polylines.last, let padding = lastPolyline.mapPadding { self.autonaviMap.showOverlays( customPolylines.map { $0.polyline }, edgePadding: UIEdgeInsets( top: padding.top, left: padding.left, bottom: padding.bottom, right: padding.right ), animated: true ) }*/ } .store(in: &cancellables) //移动至多个点的位置,并提供设置padding距离 viewModel.$suitableLocation .receive(on: DispatchQueue.main) .sink{ [weak self] polylines in if let padding = polylines.last?.mapPadding { if let atMapPoint : [CLLocationCoordinate2D] = polylines.last?.points { self?.autonaviMap.moveToSuitableLocation(points: atMapPoint, padding: padding) //self?.mapView.moveToSuitableLocation(points: atMapPoint, padding: padding) } } } .store(in: &cancellables) /*viewModel.$polylines .receive(on: DispatchQueue.main) .sink { [weak self] polylines in guard let self else { return } // 清除旧覆盖物 self.autonaviMap.removeOverlays(self.autonaviMap.overlays) // 空数据检查 guard !polylines.isEmpty else { print("轨迹数据为空") return } // 处理每条轨迹 var validPolylines: [MAPolyline] = [] for polyline in polylines { // 坐标数量检查 guard !polyline.points.isEmpty else { print("发现空坐标的轨迹: \(polyline.id)") continue } // 指针转换 let creationResult = polyline.points.withUnsafeBufferPointer { bufferPointer -> MAPolyline? in guard let baseAddress = bufferPointer.baseAddress, bufferPointer.count > 0 else { return nil } let unsafePointer = UnsafeMutablePointer(mutating: baseAddress) return MAPolyline( coordinates: unsafePointer, count: UInt(bufferPointer.count) ) } // 结果检查 guard let mapPolyline = creationResult else { print("轨迹创建失败: \(polyline.id)") continue } // 绑定属性 mapPolyline.associatedData = [ "id": polyline.id, "color": polyline.color, "width": polyline.width ] validPolylines.append(mapPolyline) } // 添加有效轨迹 guard !validPolylines.isEmpty else { print("没有有效的轨迹数据") return } self.autonaviMap.addOverlays(validPolylines) // 调整视野 if let lastValid = validPolylines.last, let padding = polylines.last?.mapPadding { self.autonaviMap.showOverlays( validPolylines, edgePadding: UIEdgeInsets( top: padding.top, left: padding.left, bottom: padding.bottom, right: padding.right ), animated: true ) } } .store(in: &cancellables) viewModel.$markers .receive(on: DispatchQueue.main) .sink { [weak self] markers in self?.mapView.removeAnnotations(self?.mapView.annotations ?? []) UIView.animate(withDuration: 0.3) { self?.mapView.addAnnotations(markers) } } .store(in: &cancellables) viewModel.$polylines .receive(on: DispatchQueue.main) .sink { [weak self] polylines in self?.mapView.removeOverlays(self?.mapView.overlays ?? []) 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) }) ?? [], padding: padding.padding, animated: true ) } } .store(in: &cancellables) //移动至多个点的位置,并提供设置padding距离 viewModel.$suitableLocation .receive(on: DispatchQueue.main) .sink{ [weak self] polylines in if let padding = polylines.last?.mapPadding { if let atMapPoint : [CLLocationCoordinate2D] = polylines.last?.points { self?.mapView.moveToSuitableLocation(points: atMapPoint, padding: padding) } } } .store(in: &cancellables)*/ } /*private func bindViewModel() { viewModel.$markers .receive(on: DispatchQueue.main) .sink { [weak self] markers in self?.autonaviMap.removeAnnotations(self?.autonaviMap.annotations) var mapMarkerList = [MAPointAnnotation](); for markerItem in markers { let annotationItem : MAPointAnnotation = MAPointAnnotation() annotationItem.title = markerItem.markerName; annotationItem.coordinate = markerItem.coordinate; mapMarkerList.append(annotationItem) } self?.autonaviMap.addAnnotations(mapMarkerList) self?.autonaviMap.selectAnnotation(mapMarkerList.first, animated: true) self?.autonaviMap.setZoomLevel(15.1, animated: true) let selectIemt : MAPointAnnotation = mapMarkerList.first! self?.autonaviMap.setCenter(selectIemt.coordinate, animated: true) //self?.mapView.removeAnnotations(self?.mapView.annotations ?? []) // UIView.animate(withDuration: 0.3) { // self?.mapView.addAnnotations(markers) // } } .store(in: &cancellables) viewModel.$currentRegion .compactMap { $0 } .receive(on: DispatchQueue.main) .sink { [weak self] region in self?.mapView.setRegion(region, animated: true) } .store(in: &cancellables) viewModel.$markers .receive(on: DispatchQueue.main) .sink { [weak self] markers in self?.mapView.removeAnnotations(self?.mapView.annotations ?? []) UIView.animate(withDuration: 0.3) { self?.mapView.addAnnotations(markers) } } .store(in: &cancellables) viewModel.$polylines .receive(on: DispatchQueue.main) .sink { [weak self] polylines in self?.mapView.removeOverlays(self?.mapView.overlays ?? []) 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) }) ?? [], padding: padding.padding, animated: true ) } } .store(in: &cancellables) //移动至多个点的位置,并提供设置padding距离 viewModel.$suitableLocation .receive(on: DispatchQueue.main) .sink{ [weak self] polylines in if let padding = polylines.last?.mapPadding { if let atMapPoint : [CLLocationCoordinate2D] = polylines.last?.points { self?.mapView.moveToSuitableLocation(points: atMapPoint, padding: padding) } } } .store(in: &cancellables) }*/ } // 自定义Polyline包装类 private class CustomPolyline { let polyline: MAPolyline let id: String let color: String let width: Double init(polyline: MAPolyline, id: String, color: String, width: Double) { self.polyline = polyline self.id = id self.color = color self.width = width } } private class MyMAPointAnnotation : MAPointAnnotation { let itemMarker : ATMapMarker init(itemMarker: ATMapMarker) { self.itemMarker = itemMarker } } private class MyMAPolyline : MAPolyline { var itemPolyLine : ATMapPolyline! = nil } @available(iOS 13.0, *) extension MapAmapThemeControl : MAMapViewDelegate { //根据anntation生成对应的View。 func mapView(_ mapView: MAMapView!, viewFor annotation: MAAnnotation!) -> MAAnnotationView! { // guard let marker = annotation as? ATMapMarker else { // return nil // } if let myitemAnnotation = annotation as? MyMAPointAnnotation { if myitemAnnotation.itemMarker.markerType.isMapAchorPoint { let annotationView = (mapView.dequeueReusableAnnotationView(withIdentifier: MapAnnotationAnchorPointView.identifier) as? MapAnnotationAnchorPointView) ?? MapAnnotationAnchorPointView(annotation: (myitemAnnotation as MAAnnotation), reuseIdentifier: MapAnnotationAnchorPointView.identifier) annotationView!.marker = myitemAnnotation.itemMarker return annotationView } else if (myitemAnnotation.itemMarker.markerType.isTracePopup) { let annotationBubbleView = (mapView.dequeueReusableAnnotationView(withIdentifier: MapAmapPopUpWindowView.identifier) as? MapAmapPopUpWindowView) ?? MapAmapPopUpWindowView(annotation: (myitemAnnotation as MAAnnotation), reuseIdentifier: MapAmapPopUpWindowView.identifier) annotationBubbleView!.marker = myitemAnnotation.itemMarker return annotationBubbleView } let annotationView = (mapView.dequeueReusableAnnotationView(withIdentifier: MapAnnotationView.identifier) as? MapAnnotationView) ?? MapAnnotationView(annotation: (myitemAnnotation as MAAnnotation), reuseIdentifier: MapAnnotationView.identifier) annotationView!.marker = myitemAnnotation.itemMarker return annotationView } return nil /*if annotation is MyMAPointAnnotation,let myitemAnnotation = annotation as? MyMAPointAnnotation { let pointReuseIdentifier = "pointReuseIndetifier" var annotationView = mapView.dequeueReusableAnnotationView( withIdentifier: pointReuseIdentifier ) as? MAPinAnnotationView if annotationView == nil { annotationView = MAPinAnnotationView( annotation: annotation, reuseIdentifier: pointReuseIdentifier ) } annotationView?.canShowCallout = true annotationView?.animatesDrop = true annotationView?.isDraggable = false annotationView?.pinColor = .purple return annotationView } return nil*/ } func mapView(_ mapView: MAMapView!, rendererFor overlay: MAOverlay!) -> MAOverlayRenderer! { guard let polyline = overlay as? MyMAPolyline else { return MAPolylineRenderer(polyline: overlay as? MAPolyline) } // 外层边框(粗线) // let borderRenderer = MAPolylineRenderer(polyline: polyline) // borderRenderer?.lineWidth = 8 // borderRenderer?.strokeColor = UIColor(red: 0.35, green: 0.36, blue: 0.99, alpha: 1) // let renderer = MAPolylineRenderer(polyline: polyline) renderer?.lineWidth = 12 renderer?.lineCapType = kMALineCapRound//kMALineCapArrow renderer?.lineJoinType = kMALineJoinRound // 设置箭头样式 // 加载箭头纹理图片 //normal error selected color if polyline.itemPolyLine.lineType == "normal" { renderer?.strokeImage = readImageContentFrom(imageName: "com.shishi.dingwei_bluearrow") //renderer?.strokeColor = UIColor(red: 0.27, green: 0.46, blue: 1, alpha: 1) } else if polyline.itemPolyLine.lineType == "error" { //renderer?.strokeColor = UIColor(red: 1, green: 0.43, blue: 0.43, alpha: 1) renderer?.strokeImage = readImageContentFrom(imageName: "com.shishi.dingwei_redarrow") } else if polyline.itemPolyLine.lineType == "selected" { //renderer?.strokeColor = UIColor(red: 0.08, green: 0.8, blue: 0.63, alpha: 1) renderer?.strokeImage = readImageContentFrom(imageName: "com.shishi.dingwei_greetarrow") } else if polyline.itemPolyLine.lineType == "color" { renderer?.strokeColor = UIColor(red: 0.27, green: 0.46, blue: 1, alpha: 1) renderer?.lineWidth = polyline.itemPolyLine.width renderer?.sideColor = UIColor(red: 0.35, green: 0.36, blue: 0.99, alpha: 1) renderer?.is3DArrowLine = true renderer?.fillColor = UIColor(hex: polyline.itemPolyLine.color)//UIColor.init(hex: "#4476FF");//UIColor(red: 123 / 255, green: 125 / 255, blue: 255 / 255, alpha: 1) } return renderer } private func readImageContentFrom(imageName : String) -> UIImage { if let image = UIImage(named: imageName) { return image } // 尝试从插件资源束加载 let bundleURL = Bundle(for: MapAnnotationView.self).url(forResource: "map_amap_ios_image_source", withExtension: "bundle") if let bundleURL = bundleURL, let resourceBundle = Bundle(url: bundleURL) { return UIImage(named: imageName, in: resourceBundle, compatibleWith: nil) ?? UIImage() } return UIImage() } } /* @available(iOS 13.0, *) extension MapAmapThemeControl: MKMapViewDelegate { func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { guard let marker = annotation as? ATMapMarker else { return nil } print("markerTypesfdsdfs---\(marker.markerType.markType)"); if marker.markerType.isMapAchorPoint { let annotationView = (mapView.dequeueReusableAnnotationView(withIdentifier: MapAnnotationAnchorPointView.identifier) as? MapAnnotationAnchorPointView) ?? MapAnnotationAnchorPointView(annotation: marker, reuseIdentifier: MapAnnotationAnchorPointView.identifier) annotationView.marker = marker annotationView.prepareForDisplay() return annotationView } else if (marker.markerType.isTracePopup) { let annotationBubbleView = (mapView.dequeueReusableAnnotationView(withIdentifier: MapAmapPopUpWindowView.identifier) as? MapAmapPopUpWindowView) ?? MapAmapPopUpWindowView(annotation: marker, reuseIdentifier: MapAmapPopUpWindowView.identifier) annotationBubbleView.marker = marker annotationBubbleView.prepareForDisplay() return annotationBubbleView } let annotationView = (mapView.dequeueReusableAnnotationView(withIdentifier: MapAnnotationView.identifier) as? MapAnnotationView) ?? MapAnnotationView(annotation: marker, reuseIdentifier: MapAnnotationView.identifier) annotationView.marker = marker annotationView.prepareForDisplay() return annotationView } func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) { guard var marker = view.annotation as? ATMapMarker else { return } viewModel.handleMarkerTap(marker: &marker) } func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { guard let polyline = overlay as? MKPolyline else { return MKOverlayRenderer(overlay: overlay) } let renderer = MapAmapArrowPolylineRenderer(polyline: polyline) renderer.lineWidth = 6 //rgba(123, 125, 255, 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 = 50 // 减小箭头间距 renderer.borderWidth = 1 renderer.borderColor = UIColor(red: 0.35, green: 0.36, blue: 0.99, alpha: 1) //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) } else if polyline.associatedLineType == "color" { renderer.strokeColor = UIColor(hex: polyline.associatedColor ?? "#4476FF") renderer.lineWidth = polyline.associatedWidth ?? 0 } return renderer } }*/