MapViewController.swift 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. //
  2. // MapViewController.swift
  3. // Runner
  4. //
  5. // Created by Groot on 2025/5/7.
  6. //
  7. import UIKit
  8. import MapKit
  9. import Combine
  10. class MapViewController: UIViewController {
  11. required init?(coder: NSCoder) {
  12. fatalError("init(coder:) has not been implemented")
  13. }
  14. let viewModel: MapViewModel
  15. let mapView = MKMapView()
  16. private var cancellables = Set<AnyCancellable>()
  17. init(viewModel: MapViewModel) {
  18. self.viewModel = viewModel
  19. super.init(nibName: nil, bundle: nil)
  20. mapView.showsUserLocation = false
  21. }
  22. override func viewDidLoad() {
  23. super.viewDidLoad()
  24. setupView()
  25. setupMap()
  26. bindViewModel()
  27. }
  28. private func setupView() {
  29. mapView.translatesAutoresizingMaskIntoConstraints = false
  30. view.addSubview(mapView)
  31. NSLayoutConstraint.activate([
  32. mapView.topAnchor.constraint(equalTo: view.topAnchor),
  33. mapView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
  34. mapView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
  35. mapView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
  36. ])
  37. }
  38. private func setupMap() {
  39. mapView.delegate = self
  40. mapView.showsUserLocation = false
  41. mapView.mapType = .mutedStandard
  42. }
  43. private func bindViewModel() {
  44. viewModel.$currentRegion
  45. .compactMap { $0 }
  46. .receive(on: DispatchQueue.main)
  47. .sink { [weak self] region in
  48. self?.mapView.setRegion(region, animated: true)
  49. }
  50. .store(in: &cancellables)
  51. viewModel.$markers
  52. .receive(on: DispatchQueue.main)
  53. .sink { [weak self] markers in
  54. self?.mapView.removeAnnotations(self?.mapView.annotations ?? [])
  55. UIView.animate(withDuration: 0.3) {
  56. self?.mapView.addAnnotations(markers)
  57. }
  58. }
  59. .store(in: &cancellables)
  60. viewModel.$polylines
  61. .receive(on: DispatchQueue.main)
  62. .sink { [weak self] polylines in
  63. self?.mapView.removeOverlays(self?.mapView.overlays ?? [])
  64. self?.mapView.addOverlays(polylines.map({ $0.polyline }))
  65. if let padding = polylines.last?.mapPadding {
  66. self?.mapView.fitsAllPoints(
  67. points: polylines.last?.points.compactMap({ MKMapPoint($0) }) ?? [],
  68. padding: padding.padding,
  69. animated: true
  70. )
  71. }
  72. }
  73. .store(in: &cancellables)
  74. //移动至多个点的位置,并提供设置padding距离
  75. viewModel.$suitableLocation
  76. .receive(on: DispatchQueue.main)
  77. .sink{ [weak self] polylines in
  78. if let padding = polylines.last?.mapPadding {
  79. if let atMapPoint : [CLLocationCoordinate2D] = polylines.last?.points {
  80. self?.mapView.moveToSuitableLocation(points: atMapPoint, padding: padding)
  81. }
  82. }
  83. }
  84. .store(in: &cancellables)
  85. }
  86. }
  87. extension MapViewController: MKMapViewDelegate {
  88. func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
  89. guard let marker = annotation as? ATMapMarker else {
  90. return nil
  91. }
  92. let annotationView = (mapView.dequeueReusableAnnotationView(withIdentifier: MapAnnotationView.identifier) as? MapAnnotationView) ?? MapAnnotationView(annotation: marker, reuseIdentifier: MapAnnotationView.identifier)
  93. annotationView.marker = marker
  94. annotationView.prepareForDisplay()
  95. return annotationView
  96. }
  97. func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
  98. guard var marker = view.annotation as? ATMapMarker else {
  99. return
  100. }
  101. viewModel.handleMarkerTap(marker: &marker)
  102. }
  103. func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
  104. let renderer = MKPolylineRenderer(overlay: overlay)
  105. renderer.lineWidth = 6
  106. //rgba(123, 125, 255, 1)
  107. renderer.strokeColor = UIColor(red: 123 / 255, green: 125 / 255, blue: 255 / 255, alpha: 1)
  108. renderer.lineCap = .round
  109. renderer.lineJoin = .round
  110. return renderer
  111. }
  112. }