前些天經手寫了一個物流項目,發現使用地圖的時候,真的是大坑套小坑(還是淺顯使用),所以就來記錄一下,也分享一下一些心得吧。(本文方法不兼容電腦瀏覽器使用,所以調試的時候請使用手機調試)
因為項目需要兼容h5,而我又是直接用的原生 <map> 標簽,所以引入了外部jdk: qqmap-wx-jssdk.js,可以直接在 微信小程序JavaScript SDK 下載,下載完成以后就可以把js文件解壓到項目中,因為需要改寫一點點地方,所以不推薦使用壓縮版的js
因為是wxjdk,所以第一步就先修改一些東西來兼容,(以下代碼均為查詢結果)
html地圖部分代碼:其中寬高大家自行根據需求更改
<map v-if="showMap" class="choose-map" style="width: 750rpx;height: 540rpx;" id="isUseMap" ref="UseMap" :latitude="selfLatitude" :longitude="selfLongitude" :markers="marker" :polyline="polyline" @tap="selectPoint" @markertap="markettap" @callouttap="callouttap" @regionchange="regionchange" :scale="scale" ></map>
其中所代表的是什么我就不一一說明了,v-if判斷是為了解決地圖展示后標記點有可能會失敗的情況,所以我在獲取到當前位置標點的時候在渲染地圖,這里所謂仁者見仁,智者見智吧。
qqmap-wx-jssdk.js:
1 /** 2 * 這里是重寫部分 3 */ 4 var vm = '' 5 6 var wx = { 7 request(obj){ 8 obj.data.output = 'jsonp' 9 vm.$jsonp(obj.url,obj.data) 10 .then(json => { 11 if(json.status == 0){ 12 obj.success(json) 13 }else { 14 obj.fail(json) 15 } 16 }) 17 .catch(err => { 18 obj.fail(err) 19 }) 20 } 21 }
改完以后保存、引入。
引入以后首先創建實例:
1 import QQMapWX from '@/common/qqmap-wx-jssdk.js'; 2 // TXMapkey是申請的qqmap key值 3 this.qqMap = new QQMapWX({ key: this.TXMapkey, vm: this });
創建完成后,就可以開始使用地圖了,使用當前地圖實例的時候可以參照上面分享的微信jdk文檔,親試可用(我覺得我應該說了句廢話)。
使用地圖:① 定位(getLocation) --> ② 標點(market) --> ③ 搜索(chooseAddress) --> ④ 路線 ;(本人技術有限,只寫了這四種常用功能,寫起代碼來很混亂兼用了好幾種方法)
① 定位(getLocation):
uniapp官方原生也給了一種獲取定位的方法(但是總是會有一些顧及不到的地方):
其中獲取定位類型有好幾種,官方原生App給出的是高德地圖支持 gcj02 類型,但是為了兼容h5所以這里使用 wgs84 類型坐標;
uni.getLocation({ type: 'wgs84', geocode: true, // 獲取地址詳情 success: res => { _that.selfLatitude = res.latitude; _that.selfLongitude = res.longitude; _that.addMarkets(res, 0); // 定位標出自身所在點 }, fail: err => {...}, complete: () => {...} });
官方原生獲取定位坐標的API,但是很可惜,他好像並不兼容h5,所以我再執行完以后(complete)里面執行了WXSDK:
// #ifdef H5 _that.qqMap.reverseGeocoder({ location: { latitude: _that.selfLatitude, longitude: _that.selfLongitude }, success: function(res) { _that.selfLatitude = res.result.location.lat; _that.selfLongitude = res.result.location.lng; _that.keyword = res.result.address; _that.addMarkets(res, 1); }, fail: function(res) {}, complete: function(res) {} }); // #endif
到這里為止可以說有百分之八十的幾率能獲取到當前位置,但是總是還有一些問題,就比如標記點的問題,也可能是定位失敗,這個坑我沒有本事直接給添上,只能又加了一種辦法(在WXJDK失敗的時候fail):
fail: function(res) { plus.geolocation.getCurrentPosition( res => { let lati = res.coords.latitude, long = res.coords.longitude, positionAddress = gcoord.transform([long, lati], gcoord.WGS84, gcoord.GCJ02); _that.selfLatitude = positionAddress[1]; _that.selfLongitude = positionAddress[0]; _that.qqMap.reverseGeocoder({ location: { latitude: positionAddress[1], longitude: positionAddress[0] }, success: function(res) { _that.selfLatitude = res.result.location.lat; _that.selfLongitude = res.result.location.lng; _that.keyword = res.result.address; _that.addMarkets(res, 1); }, fail: err => {} }); },function(err){}, { enableHighAccuracy: true, geocode: true, maximumAge: 30000, timeout: 20000 } ) }
是的!你沒有看錯,我再瘋狂的套娃,其中還是用了html5plus API plus.geolocation.getCurrentPosition 但這其中有一些問題,所以需要一個插件gcoord來把獲取到的經緯度給處理一下,我也不知道該怎么解釋,反正就是直接獲取的經緯度不能用...對
在獲取到經緯度以后我又一次的使用了WXJDK來確定當前位置並且添加標記點,到這里定位並且標記應該是沒有問題了
② 標點(market) :
// 首次添加 標記點 addMarkets(res, type) { let result; if (type == 0 || type == 2) { // 原生定位 result = { latitude: res.result.location.lat, longitude: res.result.location.lng, name: (res.address && res.address.poiName) || '' }; console.log(JSON.stringify(result)); // console.log('原生定位') } else if (type == 1) { // 騰訊定位 result = { latitude: res.result.location.lat, longitude: res.result.location.lng, name: res.result.address || '' }; // console.log('騰訊定位') } let _that = this; let market = { id: ++_that.mid, latitude: result.latitude, longitude: result.longitude, iconPath: '/static/images/market-img.png', callout: { content: result.name, color: '#ffffff', fontSize: '14', display: 'ALWAYS', bgColor: '#FF6F1E', padding: '20', textAlign: 'center', borderRadius: '25' } }; _that.markers[0] = market; _that.markers = [..._that.markers]; _that.fromAddress = result.name; _that.showMap = true; },
上面獲取定位的時候一部分上就是因為market點的問題,以上代碼就是標記點,官網比我這邊清楚。
③ 搜索(chooseAddress):
chooseAddress(type, index) {
// type是我的邏輯,index是出發地(0)與目的地(1) let _that = this; uni.chooseLocation({ keyword: _that.keyword, success: res => { let market = { id: ++_that.mid, latitude: res.latitude, longitude: res.longitude, iconPath: '/static/images/market-img.png', callout: { content: res.name, color: '#ffffff', fontSize: '14', display: 'ALWAYS', bgColor: '#FF6F1E', padding: '20', textAlign: 'center', borderRadius: '25' } }; if (index == 0) { _that.fromAddress = res.name; } if (index == 1) { _that.toAddress = res.name; } _that.includePoints[index] = market; _that.includePoints = [..._that.includePoints]; _that.markers[index] = market; _that.markers = [..._that.markers]; // 路線 _that.getTXDirection(); } });
其中標記點又出問題,問題出在了什么地方我也解釋不清楚(希望有大佬看到的話可以告知小弟),可以用計算屬性來解決:
computed: { marker() { return this.markers.slice(0, 2); }, include() { return this.includePoints.slice(0, 2); } },
④ 路線 :
這里路線我給出了兩種獲取路線的方法,大家可以參照一下:
第一種:高德地圖
// 高德獲取路線 getDirection() { let _that = this, origins = _that.markers[0].longitude + ',' + _that.markers[0].latitude, destination = _that.markers[1].longitude + ',' + _that.markers[1].latitude; this.aMapPlugin.getDrivingRoute({ origin: origins, destination: destination, success: data => { let points = []; if (data.paths && data.paths[0] && data.paths[0].steps) { var steps = data.paths[0].steps; for (var i = 0; i < steps.length; i++) { var poLen = steps[i].polyline.split(';'); for (var j = 0; j < poLen.length; j++) { points.push({ longitude: parseFloat(poLen[j].split(',')[0]), latitude: parseFloat(poLen[j].split(',')[1]) }); } } } // 線的樣式:組成點,顏色,寬度 _that.polyline = [ { points: points, color: '#FF701E', width: 7 } ]; // console.log(_that.polyline) // if (data.paths[0] && data.paths[0].distance) { // that.setData({ // distance: data.paths[0].distance + '米' // }); // } // if (data.taxi_cost) { // that.setData({ // cost: '打車約' + parseInt(data.taxi_cost) + '元' // }); // } }, fail: err => { // console.log(err); // console.log('高德獲取路線'); } }); },
第二種:騰訊地圖
1 // 騰訊地圖獲取路線 2 getTXDirection() { 3 let _that = this, 4 origins = _that.markers[0].latitude + ',' + _that.markers[0].longitude, 5 destination = _that.markers[1].latitude + ',' + _that.markers[1].longitude; 6 this.qqMap.direction({ 7 from: origins, 8 to: destination, 9 success: res => { 10 // console.log(res); 11 var ret = res; 12 var coors = ret.result.routes[0].polyline, 13 points = []; 14 //坐標解壓(返回的點串坐標,通過前向差分進行壓縮) 15 var kr = 1000000; 16 for (var i = 2; i < coors.length; i++) { 17 coors[i] = Number(coors[i - 2]) + Number(coors[i]) / kr; 18 } 19 //將解壓后的坐標放入點串數組points中 20 for (var i = 0; i < coors.length; i += 2) { 21 points.push({ latitude: coors[i], longitude: coors[i + 1] }); 22 } 23 let distance = res.result.routes[0].distance; 24 // 這個縮放問題我處理不了,頭大 25 if (distance > 500000) { 26 this.scale = 3; 27 } else if (distance > 100000) { 28 this.scale = 7; 29 } else if (distance > 10000) { 30 this.scale = 9; 31 } else if (distance > 1000) { 32 this.scale = 14; 33 } 34 _that.polyline = [ 35 { 36 points: points, 37 color: '#FF701E', 38 width: 7 39 } 40 ]; 41 // console.log(_that.polyline) 42 }, 43 fail: err => { 44 // console.log(err); 45 } 46 }); 47 },
以上就是我接觸地圖的全部內容了,唉,磕磕絆絆的總算搞完了,心累,什么時候我才能變強啊~