MKMapView+HandleTool.swift 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. //
  2. // MKMapView+HandleTool.swift
  3. // map_amap_ios
  4. //
  5. // Created by 诺诺诺的言 on 2025/7/22.
  6. //
  7. import Foundation
  8. import MapKit
  9. import MAMapKit
  10. extension MAMapView {
  11. // 按比例 按padding适应annotation
  12. /*public func fitsAllPoints(
  13. points: [MAMapPoint],
  14. padding: UIEdgeInsets,
  15. aspectRatio: Double? = nil,
  16. animated: Bool = true
  17. ) {
  18. var zoomRect: MAMapRect = MAMapRect()
  19. for point in points {
  20. let pointRect = MAMapRectMake(point.x, point.y, 0, 0)//MAMapRect(x: point.x, y: point.y, width: 0, height: 0)
  21. if zoomRectt {
  22. zoomRect = pointRect
  23. } else {
  24. zoomRect = zoomRect.union(pointRect)
  25. }
  26. }
  27. // Calculate the desired size based on the aspect ratio
  28. let aspectRatio = aspectRatio ?? 1.0
  29. let width = zoomRect.size.width
  30. let height = zoomRect.size.height
  31. let desiredWidth = max(width, height * aspectRatio)
  32. let desiredHeight = max(height, width / aspectRatio)
  33. // Calculate the center of the annotations
  34. let center = MKMapPoint(x: zoomRect.midX, y: zoomRect.midY)
  35. // Create a new MKMapRect with the desired aspect ratio and centered on the annotations
  36. let newMapRect = MKMapRect(
  37. x: center.x - desiredWidth / 2,
  38. y: center.y - desiredHeight / 2,
  39. width: desiredWidth,
  40. height: desiredHeight
  41. )
  42. setVisibleMapRect(newMapRect, edgePadding: padding, animated: animated)
  43. }
  44. func calculateMapRect(points: [MKMapPoint], padding: UIEdgeInsets = .zero) -> MKMapRect {
  45. var zoomRect: MKMapRect = .null
  46. for point in points {
  47. let pointRect = MKMapRect(x: point.x, y: point.y, width: 0, height: 0)
  48. if zoomRect.isNull {
  49. zoomRect = pointRect
  50. } else {
  51. zoomRect = zoomRect.union(pointRect)
  52. }
  53. }
  54. return mapRectThatFits(zoomRect, edgePadding: padding)
  55. }*/
  56. func takeSnapShot(option: MKMapSnapshotter.Options, completion: @escaping (MKMapSnapshotter.Snapshot?) -> Void) {
  57. let shotter = MKMapSnapshotter(options: option)
  58. shotter.start(with: .global()) { shot, _ in
  59. completion(shot)
  60. }
  61. }
  62. ///移动至多个点的位置,并提供设置padding距离
  63. func moveToSuitableLocation(points: [CLLocationCoordinate2D], padding: ATMapPadding? = nil) {
  64. // 检查是否有足够的点
  65. guard points.count > 0 else {
  66. print("Error: No points provided to calculate suitable location")
  67. return
  68. }
  69. // 1. 计算所有点的边界
  70. var minLat = points[0].latitude
  71. var maxLat = points[0].latitude
  72. var minLng = points[0].longitude
  73. var maxLng = points[0].longitude
  74. for point in points {
  75. minLat = min(minLat, point.latitude)
  76. maxLat = max(maxLat, point.latitude)
  77. minLng = min(minLng, point.longitude)
  78. maxLng = max(maxLng, point.longitude)
  79. }
  80. // 2. 创建包含所有点的区域
  81. let centerLat = (minLat + maxLat) / 2
  82. let centerLng = (minLng + maxLng) / 2
  83. let center = CLLocationCoordinate2D(latitude: centerLat, longitude: centerLng)
  84. // 计算区域跨度,添加一些额外空间
  85. let spanLat = (maxLat - minLat) * 1.1 // 增加10%的边距
  86. let spanLng = (maxLng - minLng) * 1.1
  87. // 确保跨度不为0且不过大
  88. let safeSpanLat = max(min(spanLat, 100.0), 0.001) // 设置合理的最大跨度
  89. let safeSpanLng = max(min(spanLng, 100.0), 0.001)
  90. // 创建初始区域
  91. let span = MACoordinateSpan(latitudeDelta: safeSpanLat, longitudeDelta: safeSpanLng)
  92. print("初始区域: center=\(center), span=\(span)")
  93. // 3. 创建区域并应用padding
  94. var region = MACoordinateRegion(center: center, span: span)//MKCoordinateRegion(center: center, span: span)
  95. // 应用padding(如果有)
  96. if let padding = padding {
  97. // 检查地图视图尺寸是否有效
  98. let mapViewWidth = max(self.bounds.width, 1.0) // 确保宽度至少为1
  99. let mapViewHeight = max(self.bounds.height, 1.0) // 确保高度至少为1
  100. // 基于地图视图尺寸和padding计算经纬度调整量
  101. let latPadding = span.latitudeDelta * (padding.top + padding.bottom) / mapViewHeight
  102. let lngPadding = span.longitudeDelta * (padding.left + padding.right) / mapViewWidth
  103. // 调整区域跨度以应用padding,并确保不会导致无穷大
  104. region.span.latitudeDelta = min(region.span.latitudeDelta + latPadding, 180.0)
  105. region.span.longitudeDelta = min(region.span.longitudeDelta + lngPadding, 360.0)
  106. print("应用padding后的区域: span=\(region.span)")
  107. }
  108. // 4. 验证最终区域是否有效
  109. if !isValidRegion(region) {
  110. //print("无效区域,使用默认区域")
  111. region = defaultRegion()
  112. }
  113. print("最终使用的区域: \(region)")
  114. // 设置地图区域
  115. self.setRegion(self.regionThatFits(region), animated: true)
  116. }
  117. // 辅助方法:检查区域是否有效
  118. private func isValidRegion(_ region: MACoordinateRegion) -> Bool {
  119. let center = region.center
  120. let span = region.span
  121. return !center.latitude.isNaN && !center.longitude.isNaN &&
  122. !span.latitudeDelta.isNaN && !span.longitudeDelta.isNaN &&
  123. !span.latitudeDelta.isInfinite && !span.longitudeDelta.isInfinite &&
  124. isValidCoordinate(center) &&
  125. span.latitudeDelta > 0 && span.latitudeDelta <= 180 &&
  126. span.longitudeDelta > 0 && span.longitudeDelta <= 360
  127. }
  128. // 辅助方法:提供默认有效区域
  129. private func defaultRegion() -> MACoordinateRegion {
  130. return MACoordinateRegion(center: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194), span: MACoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1))
  131. }
  132. // 辅助方法:检查坐标是否有效
  133. private func isValidCoordinate(_ coordinate: CLLocationCoordinate2D) -> Bool {
  134. return coordinate.latitude >= -90 && coordinate.latitude <= 90 &&
  135. coordinate.longitude >= -180 && coordinate.longitude <= 180
  136. }
  137. ///是否隐藏地图图标
  138. func mapLogoVisible(isHiddenLogo : Bool) {
  139. for subview in self.subviews {
  140. if let logo = subview as? UIImageView,
  141. logo.bounds.size.width <= 100,
  142. logo.bounds.size.height <= 20 {
  143. logo.isHidden = isHiddenLogo
  144. }
  145. }
  146. }
  147. }