openMap.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /**
  2. * h5、小程序、APP页面唤起地图APP导航
  3. * @tutorial https://ext.dcloud.net.cn/plugin?id=1837
  4. * @see https://github.com/fuxing1991/openMap/blob/master/js_sdk/fx-openMap/openMap.js
  5. */
  6. let itemList = ['百度地图', '高德地图', '腾讯地图'];
  7. // #ifdef APP-PLUS
  8. var isBaidu = plus.runtime.isApplicationExist({pname: 'com.baidu.BaiduMap', action: 'baidumap://'});
  9. var isGaode = plus.runtime.isApplicationExist({pname: 'com.autonavi.minimap', action: 'iosamap://'});
  10. var isQQ = plus.runtime.isApplicationExist({pname: 'com.tencent.map', action: 'qqmap://'});
  11. let AppitemList = [{title: '腾讯地图'}];
  12. if (isBaidu && isGaode) {
  13. AppitemList = [{title: '百度地图'}, {title: '高德地图'}, {title: '腾讯地图'}];
  14. }
  15. if (!isBaidu && isGaode) {
  16. AppitemList = [{title: '高德地图'}, {title: '腾讯地图'}];
  17. }
  18. if (isBaidu && !isGaode) {
  19. AppitemList = [{title: '百度地图'}, {title: '腾讯地图'}];
  20. }
  21. // #endif
  22. function openMapByAndroid(origin, destination, mode) {
  23. let originName = origin && origin.name ? origin.name : '起点';
  24. let destinationName = destination.name ? destination.name : '终点';
  25. var bdMode = 'driving';
  26. if (mode == 'bus') {
  27. bdMode = 'transit';
  28. } else if (mode == 'walk') {
  29. bdMode = 'walking';
  30. } else if (mode == 'bike') {
  31. bdMode = 'riding';
  32. }
  33. var bdapp = 'bdapp://map/direction?destination=name:' + destinationName + '|latlng:' + destination.latitude + ',' + destination.longitude + '&coord_type=gcj02&mode=' + bdMode + '&src=uniapp';
  34. if (origin) {
  35. bdapp = 'bdapp://map/direction?origin=name:' + originName + '|latlng:' + origin.latitude + ',' + origin.longitude + '&destination=name:' + destinationName + '|latlng:' + destination.latitude + ',' + destination.longitude + '&coord_type=gcj02&mode=' + bdMode + '&src=uniapp';
  36. }
  37. var bdappDown = 'http://map.baidu.com/zt/qudao/newfengchao/1012337a/html/slide.html'
  38. var amapMode = 0;
  39. if (mode == 'bus') {
  40. amapMode = 1;
  41. } else if (mode == 'walk') {
  42. amapMode = 2;
  43. } else if (mode == 'bike') {
  44. amapMode = 3;
  45. }
  46. var amapuri = 'amapuri://route/plan/?sourceApplication=uniapp&dlat=' + destination.latitude + '&dlon=' + destination.longitude + '&dname=' + destinationName + '&dev=1&t=' + amapMode;
  47. if (origin) {
  48. amapuri = 'amapuri://route/plan/?sourceApplication=uniapp&slat=' + origin.latitude + '&slon=' + origin.longitude + '&sname=' + originName + '&dlat=' + destination.latitude + '&dlon=' + destination.longitude + '&dname=' + destinationName + '&dev=1&t=' + amapMode;
  49. }
  50. var amapuriDown = 'http://wap.amap.com/';
  51. var qqmap = 'qqmap://map/routeplan?type=' + mode + '&to=' + destinationName + '&tocoord=' + destination.latitude + ',' + destination.longitude;
  52. if (origin) {
  53. qqmap = 'qqmap://map/routeplan?type=' + mode + '&from=' + originName + '&fromcoord=' + origin.latitude + ',' + origin.longitude + '&to=' + destinationName + '&tocoord=' + destination.latitude + ',' + destination.longitude;
  54. }
  55. var qqmapDefault = 'https://apis.map.qq.com/uri/v1/routeplan?type=' + mode + '&to=' + destinationName + '&tocoord=' + destination.latitude + ',' + destination.longitude + '&policy=1';
  56. if (origin) {
  57. qqmapDefault = 'https://apis.map.qq.com/uri/v1/routeplan?type=' + mode + '&from=' + originName + '&fromcoord=' + origin.latitude + ',' + origin.longitude + '&to=' + destinationName + '&tocoord=' + destination.latitude + ',' + destination.longitude + '&policy=1';
  58. }
  59. // #ifdef APP-PLUS
  60. plus.nativeUI.actionSheet(
  61. {
  62. // title:"选择导航",
  63. cancel: '取消',
  64. buttons: AppitemList
  65. },
  66. function(res) {
  67. if (isBaidu && isGaode) {
  68. if (res.index == 1) {
  69. plus.runtime.openURL(bdapp);
  70. } else if (res.index == 2) {
  71. plus.runtime.openURL(amapuri);
  72. } else if (res.index == 3) {
  73. if (isQQ) {
  74. plus.runtime.openURL(qqmap);
  75. } else {
  76. plus.runtime.openURL(qqmapDefault);
  77. }
  78. }
  79. } else if (!isBaidu && isGaode) {
  80. if (res.index == 1) {
  81. plus.runtime.openURL(amapuri);
  82. } else if (res.index == 2) {
  83. if (isQQ) {
  84. plus.runtime.openURL(qqmap);
  85. } else {
  86. plus.runtime.openURL(qqmapDefault);
  87. }
  88. }
  89. } else if (isBaidu && !isGaode) {
  90. if (res.index == 1) {
  91. plus.runtime.openURL(bdapp);
  92. } else if (res.index == 2) {
  93. if (isQQ) {
  94. plus.runtime.openURL(qqmap);
  95. } else {
  96. plus.runtime.openURL(qqmapDefault);
  97. }
  98. }
  99. } else {
  100. if (res.index == 1) {
  101. if (isQQ) {
  102. plus.runtime.openURL(qqmap);
  103. } else {
  104. plus.runtime.openURL(qqmapDefault);
  105. }
  106. }
  107. }
  108. }
  109. );
  110. // #endif
  111. // #ifndef APP-PLUS
  112. uni.showActionSheet({
  113. itemList: itemList,
  114. success: (res) => {
  115. if (res.tapIndex == 0) {
  116. openURL(bdapp, bdappDown)
  117. } else if (res.tapIndex == 1) {
  118. openURL(amapuri, amapuriDown)
  119. } else {
  120. openURL(qqmap, qqmapDefault)
  121. }
  122. }
  123. })
  124. // #endif
  125. }
  126. function openMapByIos(origin, destination, mode) {
  127. let originName = origin && origin.name ? origin.name : '起点';
  128. let destinationName = destination.name ? destination.name : '终点';
  129. var bdMode = 'driving';
  130. if (mode == 'bus') {
  131. bdMode = 'transit';
  132. } else if (mode == 'walk') {
  133. bdMode = 'walking';
  134. } else if (mode == 'bike') {
  135. bdMode = 'riding';
  136. }
  137. var bdapp = 'baidumap://map/direction?destination=name:' + destinationName + '|latlng:' + destination.latitude + ',' + destination.longitude + '&coord_type=gcj02&mode=' + bdMode + '&src=uniapp';
  138. if (origin) {
  139. bdapp = 'baidumap://map/direction?origin=name:' + originName + '|latlng:' + origin.latitude + ',' + origin.longitude + '&destination=name:' + destinationName + '|latlng:' + destination.latitude + ',' + destination.longitude + '&coord_type=gcj02&mode=' + bdMode + '&src=uniapp';
  140. }
  141. var bdappDown = 'http://map.baidu.com/zt/qudao/newfengchao/1012337a/html/slide.html';
  142. var amapMode = 0;
  143. if (mode == 'bus') {
  144. amapMode = 1;
  145. } else if (mode == 'walk') {
  146. amapMode = 2;
  147. } else if (mode == 'bike') {
  148. amapMode = 3;
  149. }
  150. var amapuri = 'iosamap://route/plan/?sourceApplication=uniapp&dlat=' + destination.latitude + '&dlon=' + destination.longitude + '&dname=' + destinationName + '&dev=1&t=' + amapMode;
  151. if (origin) {
  152. amapuri = 'iosamap://route/plan/?sourceApplication=uniapp&slat=' + origin.latitude + '&slon=' + origin.longitude + '&sname=' + originName + '&dlat=' + destination.atitude + '&dlon=' + destination.longitude + '&dname=' + destinationName + '&dev=1&t=' + amapMode;
  153. }
  154. var amapuriDown = 'http://wap.amap.com/';
  155. var qqmap = 'qqmap://map/routeplan?type=' + mode + '&to=' + destinationName + '&tocoord=' + destination.latitude + ',' + destination.longitude;
  156. if (origin) {
  157. qqmap = 'qqmap://map/routeplan?type=' + mode + '&from=' + originName + '&fromcoord=' + origin.latitude + ',' + origin.longitude + '&to=' + destinationName + '&tocoord=' + destination.latitude + ',' + destination.longitude;
  158. }
  159. var qqmapDefault = 'https://apis.map.qq.com/uri/v1/routeplan?type=' + mode + '&to=' + destinationName + '&tocoord=' + destination.latitude + ',' + destination.longitude + '&policy=1';
  160. if (origin) {
  161. qqmapDefault = 'https://apis.map.qq.com/uri/v1/routeplan?type=' + mode + '&from=' + originName + '&fromcoord=' + origin.latitude + ',' + origin.longitude + '&to=' + destinationName + '&tocoord=' + destination.latitude + ',' + destination.longitude + '&policy=1';
  162. }
  163. // #ifdef APP-PLUS
  164. plus.nativeUI.actionSheet(
  165. {
  166. // title:"选择导航",
  167. cancel: '取消',
  168. buttons: AppitemList
  169. },
  170. function(res) {
  171. if (isBaidu && isGaode) {
  172. if (res.index == 1) {
  173. plus.runtime.openURL(bdapp);
  174. } else if (res.index == 2) {
  175. plus.runtime.openURL(amapuri);
  176. } else if (res.index == 3) {
  177. if (isQQ) {
  178. plus.runtime.openURL(qqmap);
  179. } else {
  180. plus.runtime.openURL(qqmapDefault);
  181. }
  182. }
  183. } else if (!isBaidu && isGaode) {
  184. if (res.index == 1) {
  185. plus.runtime.openURL(amapuri);
  186. } else if (res.index == 2) {
  187. if (isQQ) {
  188. plus.runtime.openURL(qqmap);
  189. } else {
  190. plus.runtime.openURL(qqmapDefault);
  191. }
  192. }
  193. } else if (isBaidu && !isGaode) {
  194. if (res.index == 1) {
  195. plus.runtime.openURL(bdapp);
  196. } else if (res.index == 2) {
  197. if (isQQ) {
  198. plus.runtime.openURL(qqmap);
  199. } else {
  200. plus.runtime.openURL(qqmapDefault);
  201. }
  202. }
  203. } else {
  204. if (res.index == 1) {
  205. if (isQQ) {
  206. plus.runtime.openURL(qqmap);
  207. } else {
  208. plus.runtime.openURL(qqmapDefault);
  209. }
  210. }
  211. }
  212. }
  213. );
  214. // #endif
  215. // #ifndef APP-PLUS
  216. uni.showActionSheet({
  217. itemList: itemList,
  218. success: (res) => {
  219. if (res.tapIndex == 0) {
  220. openURL(bdapp, bdappDown)
  221. } else if (res.tapIndex == 1) {
  222. openURL(amapuri, amapuriDown)
  223. } else {
  224. openURL(qqmap, qqmapDefault)
  225. }
  226. }
  227. })
  228. // #endif
  229. }
  230. function openURL(url, downLoadUrl) {
  231. window.location.href = url;
  232. var startTime = Date.now();
  233. var count = 0;
  234. var endTime = 0;
  235. var t = setInterval(function() {
  236. count += 1;
  237. endTime = Date.now() - startTime;
  238. if (endTime > 800) {
  239. clearInterval(t);
  240. }
  241. if (count < 40) {
  242. return false;
  243. }
  244. if (!(document.hidden || document.webkitHidden)) {
  245. window.location.href = downLoadUrl;
  246. }
  247. }, 20);
  248. }
  249. let PI = 3.14159265358979324;
  250. let x_pi = 3.14159265358979324 * 3000.0 / 180.0
  251. function delta(lat, lon) {
  252. var a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
  253. var ee = 0.00669342162296594323; // ee: 椭球的偏心率。
  254. var dLat = transformLat(lon - 105.0, lat - 35.0);
  255. var dLon = transformLon(lon - 105.0, lat - 35.0);
  256. var radLat = lat / 180.0 * PI;
  257. var magic = Math.sin(radLat);
  258. magic = 1 - ee * magic * magic;
  259. var sqrtMagic = Math.sqrt(magic);
  260. dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI);
  261. dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * PI);
  262. return {'lat': dLat, 'lon': dLon};
  263. }
  264. function gcj_encrypt(wgsLat, wgsLon) {
  265. if (outOfChina(wgsLat, wgsLon)) { return {'lat': wgsLat, 'lon': wgsLon}; }
  266. var d = delta(wgsLat, wgsLon);
  267. return {'lat': wgsLat + d.lat, 'lon': wgsLon + d.lon};
  268. }
  269. function bd_decrypt(bdLat, bdLon) {
  270. var x = bdLon - 0.0065, y = bdLat - 0.006;
  271. var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
  272. var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
  273. var gcjLon = z * Math.cos(theta);
  274. var gcjLat = z * Math.sin(theta);
  275. return {'lat': gcjLat, 'lon': gcjLon};
  276. }
  277. function outOfChina(lat, lon) {
  278. if (lon < 72.004 || lon > 137.8347) { return true; }
  279. if (lat < 0.8293 || lat > 55.8271) { return true; }
  280. return false;
  281. }
  282. function transformLat(x, y) {
  283. var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
  284. ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
  285. ret += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0;
  286. ret += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0;
  287. return ret;
  288. }
  289. function transformLon(x, y) {
  290. var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
  291. ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0;
  292. ret += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0;
  293. ret += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0 * PI)) * 2.0 / 3.0;
  294. return ret;
  295. }
  296. export default {
  297. /* 打开地图 */
  298. openMap(options, type = 'gcj02') {
  299. let _origin = options.origin, _destination = options.destination, _mode = options.mode ? options.mode : 'drive';
  300. if (type.toLowerCase() == 'wgs84') {
  301. if (options.origin) {
  302. _origin.latitude = gcj_encrypt(options.origin.latitude, options.origin.longitude).lat
  303. _origin.longitude = gcj_encrypt(options.origin.latitude, options.origin.longitude).lon
  304. }
  305. _destination.latitude = gcj_encrypt(options.destination.latitude, options.destination.longitude).lat
  306. _destination.longitude = gcj_encrypt(options.destination.latitude, options.destination.longitude).lon
  307. } else if (type.toLowerCase() == 'bd09') {
  308. if (options.origin) {
  309. _origin.latitude = bd_decrypt(options.origin.latitude, options.origin.longitude).lat
  310. _origin.longitude = bd_decrypt(options.origin.latitude, options.origin.longitude).lon
  311. }
  312. _destination.latitude = bd_decrypt(options.destination.latitude, options.destination.longitude).lat
  313. _destination.longitude = bd_decrypt(options.destination.latitude, options.destination.longitude).lon
  314. }
  315. // #ifdef MP
  316. // #ifdef MP-WEIXIN
  317. wx.openLocation({
  318. latitude: _destination.latitude,
  319. longitude: _destination.longitude,
  320. name: _destination.name
  321. })
  322. // #endif
  323. // #ifdef MP-QQ
  324. qq.openLocation({
  325. latitude: _destination.latitude,
  326. longitude: _destination.longitude,
  327. name: _destination.name
  328. })
  329. // #endif
  330. // #ifdef MP-ALIPAY
  331. my.openLocation({
  332. latitude: _destination.latitude,
  333. longitude: _destination.longitude,
  334. name: _destination.name
  335. })
  336. // #endif
  337. // #ifdef MP-360 || MP-BAIDU || MP-TOUTIAO
  338. uni.openLocation({
  339. latitude: _destination.latitude,
  340. longitude: _destination.longitude,
  341. name: _destination.name
  342. })
  343. // #endif
  344. // #endif
  345. // #ifndef MP
  346. switch (uni.getSystemInfoSync().platform) {
  347. case 'android':
  348. console.log('运行Android上')
  349. openMapByAndroid(_origin, _destination, _mode)
  350. break;
  351. case 'ios':
  352. console.log('运行iOS上')
  353. openMapByIos(_origin, _destination, _mode)
  354. break;
  355. default:
  356. console.log('运行在开发者工具上')
  357. break;
  358. }
  359. // #endif
  360. }
  361. }