IMShowLocationViewController.swift 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. //
  2. // IMShowLocationViewController.swift
  3. // O2Platform
  4. //
  5. // Created by FancyLou on 2020/6/18.
  6. // Copyright © 2020 zoneland. All rights reserved.
  7. //
  8. import UIKit
  9. import MapKit
  10. import CocoaLumberjack
  11. class IMShowLocationViewController: UIViewController {
  12. // MARK: - 在地图上展现一个位置,这里的经纬度是百度的经纬度
  13. public static func pushShowLocation(vc: UIViewController, latitude: Double?, longitude: Double?,
  14. address: String?, addressDetail: String?) {
  15. let map = IMShowLocationViewController()
  16. map.address = address
  17. map.addressDetail = addressDetail
  18. map.latitude = latitude
  19. map.longitude = longitude
  20. vc.navigationController?.pushViewController(map, animated: false)
  21. }
  22. private var mapView: BMKMapView!
  23. private var annotation: BMKPointAnnotation!
  24. var address: String?
  25. var addressDetail: String?
  26. var latitude: Double?
  27. var longitude: Double?
  28. //换算后的火星坐标 其他地图都用这个坐标
  29. var gcj02Location: CLLocationCoordinate2D? = nil
  30. override func viewDidLoad() {
  31. super.viewDidLoad()
  32. self.title = address
  33. mapView = BMKMapView(frame: CGRect(x: 0, y: 0, width: SCREEN_WIDTH ,height: SCREEN_HEIGHT))
  34. mapView.zoomLevel = 17
  35. mapView.showMapPoi = true
  36. mapView.showIndoorMapPoi = true
  37. self.view.addSubview(mapView)
  38. guard let lat = latitude, let lo = longitude else {
  39. self.showError(title: "没有传入正确的地址参数!")
  40. return
  41. }
  42. //更新地图位置
  43. let user = BMKUserLocation()
  44. let loc = CLLocation(latitude: lat, longitude: lo)
  45. user.location = loc
  46. mapView.updateLocationData(user)
  47. mapView.centerCoordinate = CLLocationCoordinate2D(latitude: loc.coordinate.latitude, longitude: loc.coordinate.longitude)
  48. //设置位置点
  49. annotation = BMKPointAnnotation()
  50. annotation.coordinate = loc.coordinate
  51. annotation.title = address
  52. annotation.subtitle = addressDetail
  53. mapView.addAnnotation(annotation)
  54. self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "share"), style: .plain, target: self, action: #selector(openOtherMap))
  55. self.bd09Decrypt(CLLocationCoordinate2D(latitude: lat, longitude: lo)) { (ll) in
  56. self.gcj02Location = ll
  57. }
  58. }
  59. @objc private func openOtherMap() {
  60. self.showSheetAction(title: nil, message: nil, actions: [
  61. UIAlertAction(title: "百度地图", style: .default, handler: { (action) in
  62. self.openMap(url: self.baiduMapUrl())
  63. }),
  64. UIAlertAction(title: "高德地图", style: .default, handler: { (action) in
  65. self.openMap(url: self.aMapUrl())
  66. }),
  67. UIAlertAction(title: "腾讯地图", style: .default, handler: { (action) in
  68. self.openMap(url: self.tencentMapUrl())
  69. }),
  70. UIAlertAction(title: "Apple 地图", style: .default, handler: { (action) in
  71. self.openAppleMap()
  72. })
  73. ])
  74. }
  75. private func openMap(url: URL?) {
  76. if let u = url {
  77. DDLogDebug("打开地图 url:\(u)")
  78. UIApplication.shared.open(u, options: [:], completionHandler: nil)
  79. }else {
  80. DDLogError("没有生成url//。。。。。")
  81. self.showError(title: "未安装该地图app,无法打开")
  82. }
  83. }
  84. private func openAppleMap() {
  85. if let gcj02 = self.gcj02Location {
  86. let currentLocation = MKMapItem.forCurrentLocation()
  87. let toLocation = MKMapItem(placemark: MKPlacemark(coordinate: gcj02))
  88. toLocation.name = self.address
  89. MKMapItem.openMaps(with: [currentLocation, toLocation], launchOptions: [
  90. MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving,
  91. MKLaunchOptionsShowsTrafficKey: NSNumber(booleanLiteral: true)
  92. ])
  93. }else {
  94. DDLogError("没有转化后的坐标。。。。。。。。")
  95. }
  96. }
  97. //百度地图
  98. private func baiduMapUrl() -> URL? {
  99. if UIApplication.shared.canOpenURL(URL(string: "baidumap://")!) {
  100. let url = "baidumap://map/direction?origin=我的位置&destination=latlng:\(latitude ?? 0),\(longitude ?? 0)|name:\(address ?? "")&mode=driving&coord_type=bd09ll&src=net.zoneland.m.o2oa"
  101. return URL(string: url.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed) ?? "")
  102. }
  103. return nil
  104. }
  105. //高德地图
  106. private func aMapUrl() -> URL? {
  107. //&sid=BGVIS1&did=BGVIS2
  108. if UIApplication.shared.canOpenURL(URL(string: "iosamap://")!) {
  109. let url = "iosamap://path?sourceApplication=O2OA&dlat=\(self.gcj02Location?.latitude ?? 0)&dlon=\(self.gcj02Location?.longitude ?? 0)&dname=\(self.address ?? "")&dev=0&t=0"
  110. return URL(string: url.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed) ?? "")
  111. }
  112. return nil
  113. }
  114. //腾讯地图
  115. private func tencentMapUrl() -> URL? {
  116. if UIApplication.shared.canOpenURL(URL(string: "qqmap://")!) {
  117. let url = "qqmap://map/routeplan?type=drive&from=我的位置&to=\(self.address ?? "")&tocoord=\(self.gcj02Location?.latitude ?? 0),\(self.gcj02Location?.longitude ?? 0)&policy=1"
  118. return URL(string: url.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed) ?? "")
  119. }
  120. return nil
  121. }
  122. // MARK: - 百度BD09坐标转火星坐标
  123. fileprivate let queue = DispatchQueue(label: "O2.LocationConverter.Converter")
  124. fileprivate func bd09Decrypt(_ bd09Point:CLLocationCoordinate2D, result:@escaping (_ gcj02Point:CLLocationCoordinate2D) -> Void) {
  125. self.queue.async {
  126. let x = bd09Point.longitude - 0.0065
  127. let y = bd09Point.latitude - 0.006
  128. let z = sqrt(x * x + y * y) - 0.00002 * sin(y * .pi);
  129. let theta = atan2(y, x) - 0.000003 * cos(x * .pi);
  130. let resultPoint = CLLocationCoordinate2DMake(z * sin(theta), z * cos(theta))
  131. DispatchQueue.main.async {
  132. result(resultPoint)
  133. }
  134. }
  135. }
  136. }