MapKit+E.swift 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. //
  2. // MapKit+E.swift
  3. // Pods
  4. //
  5. // Created by Groot on 2025/5/14.
  6. //
  7. import MapKit
  8. import Foundation
  9. extension MKMapView {
  10. // 按比例 按padding适应annotation
  11. public func fitsAllPoints(
  12. points: [MKMapPoint],
  13. padding: UIEdgeInsets,
  14. aspectRatio: Double? = nil,
  15. animated: Bool = true
  16. ) {
  17. var zoomRect: MKMapRect = .null
  18. for point in points {
  19. let pointRect = MKMapRect(x: point.x, y: point.y, width: 0, height: 0)
  20. if zoomRect.isNull {
  21. zoomRect = pointRect
  22. } else {
  23. zoomRect = zoomRect.union(pointRect)
  24. }
  25. }
  26. // Calculate the desired size based on the aspect ratio
  27. let aspectRatio = aspectRatio ?? 1.0
  28. let width = zoomRect.size.width
  29. let height = zoomRect.size.height
  30. let desiredWidth = max(width, height * aspectRatio)
  31. let desiredHeight = max(height, width / aspectRatio)
  32. // Calculate the center of the annotations
  33. let center = MKMapPoint(x: zoomRect.midX, y: zoomRect.midY)
  34. // Create a new MKMapRect with the desired aspect ratio and centered on the annotations
  35. let newMapRect = MKMapRect(
  36. x: center.x - desiredWidth / 2,
  37. y: center.y - desiredHeight / 2,
  38. width: desiredWidth,
  39. height: desiredHeight
  40. )
  41. setVisibleMapRect(newMapRect, edgePadding: padding, animated: animated)
  42. }
  43. func calculateMapRect(points: [MKMapPoint], padding: UIEdgeInsets = .zero) -> MKMapRect {
  44. var zoomRect: MKMapRect = .null
  45. for point in points {
  46. let pointRect = MKMapRect(x: point.x, y: point.y, width: 0, height: 0)
  47. if zoomRect.isNull {
  48. zoomRect = pointRect
  49. } else {
  50. zoomRect = zoomRect.union(pointRect)
  51. }
  52. }
  53. return mapRectThatFits(zoomRect, edgePadding: padding)
  54. }
  55. func takeSnapShot(option: MKMapSnapshotter.Options, completion: @escaping (MKMapSnapshotter.Snapshot?) -> Void) {
  56. let shotter = MKMapSnapshotter(options: option)
  57. shotter.start(with: .global()) { shot, _ in
  58. completion(shot)
  59. }
  60. }
  61. ///移动至多个点的位置,并提供设置padding距离
  62. func moveToSuitableLocation(points: [CLLocationCoordinate2D], padding: ATMapPadding? = nil) {
  63. // 检查是否有足够的点
  64. guard points.count > 0 else {
  65. print("Error: No points provided to calculate suitable location")
  66. return
  67. }
  68. // 1. 计算所有点的边界
  69. var minLat = points[0].latitude
  70. var maxLat = points[0].latitude
  71. var minLng = points[0].longitude
  72. var maxLng = points[0].longitude
  73. for point in points {
  74. minLat = min(minLat, point.latitude)
  75. maxLat = max(maxLat, point.latitude)
  76. minLng = min(minLng, point.longitude)
  77. maxLng = max(maxLng, point.longitude)
  78. }
  79. // 2. 创建包含所有点的区域
  80. let centerLat = (minLat + maxLat) / 2
  81. let centerLng = (minLng + maxLng) / 2
  82. let center = CLLocationCoordinate2D(latitude: centerLat, longitude: centerLng)
  83. // 计算区域跨度,添加一些额外空间
  84. let spanLat = (maxLat - minLat) * 1.1 // 增加10%的边距
  85. let spanLng = (maxLng - minLng) * 1.1
  86. // 确保跨度不为0
  87. let span = MKCoordinateSpan(
  88. latitudeDelta: max(spanLat, 0.001), // 设置最小跨度,避免点过于集中时视图缩放过度
  89. longitudeDelta: max(spanLng, 0.001)
  90. )
  91. // 3. 创建区域并应用padding
  92. var region = MKCoordinateRegion(center: center, span: span)
  93. // 应用padding(如果有)
  94. if let padding = padding {
  95. // 计算padding对应的经纬度差值
  96. let mapViewWidth = self.bounds.width
  97. let mapViewHeight = self.bounds.height
  98. // 基于地图视图尺寸和padding计算经纬度调整量
  99. let latPadding = span.latitudeDelta * (padding.top + padding.bottom) / mapViewHeight
  100. let lngPadding = span.longitudeDelta * (padding.left + padding.right) / mapViewWidth
  101. // 调整区域跨度以应用padding
  102. region.span.latitudeDelta += latPadding
  103. region.span.longitudeDelta += lngPadding
  104. }
  105. // 4. 设置地图区域
  106. // 使用animate参数控制是否动画过渡
  107. self.setRegion(self.regionThatFits(region), animated: true)
  108. }
  109. ///是否隐藏地图图标
  110. func mapLogoVisible(isHiddenLogo : Bool) {
  111. for subview in self.subviews {
  112. if let logo = subview as? UIImageView,
  113. logo.bounds.size.width <= 100,
  114. logo.bounds.size.height <= 20 {
  115. logo.isHidden = isHiddenLogo
  116. }
  117. }
  118. }
  119. }