微信小程序 + 腾讯位置服务SDK 实现路线规划
前言
本文旨在以mpvue框架為基礎,探討地圖類小程序的開發思路。 原作者利用mpvue + 騰訊地圖的能力做了一個地鐵路線規劃的小程序,主要提供全球主要城市的地鐵線網圖及旅游介紹,其中國內城市支持查看地圖和路線規劃。
目前騰訊位置服務也推出了路線規劃插件、地鐵圖插件,實現更加簡單便捷,感興趣的可點擊查看。
運行截圖
mpvue 介紹 及項目搭建
mpvue = miniprogram + vue framework,說白了就是用vue框架開發小程序。mpvue最近升級為2.x版本,支持微信、支付寶、百度和頭條小程序。和傳統方式相比,mpvue開發具有以下優點:
徹底的組件化開發能力:提高代碼復用性
-
完整的 Vue.js 開發體驗
-
方便的 Vuex 數據管理方案:方便構建復雜應用
-
快捷的 webpack 構建機制:自定義構建策略、開發階段 hotReload
-
支持使用 npm 外部依賴
-
使用 Vue.js 命令行工具 vue-cli 快速初始化項目
-
H5 代碼轉換編譯成小程序目標代碼的能力
就個人使用體驗來看,還是挺絲滑順暢的,傳統web應用開發無縫切換至小程序開發,基本零門檻。要注意的就是小程序的限制及和vue的差異:
-
小程序使用相對像素 rpx 進行樣式布局
-
部分css選擇符不支持,目前只支持 #id | .class | tag | tag,tag | ::after ::before,所以要特別注意
-
組合式生命周期,mpvue將小程序和vue的生命周期混在一塊,詳情見 mpvue.com/mpvue/#_3 ,目前這個地方還有很多坑,比如在小程序page unload時,vue實例卻沒被銷毀,導致下次進入頁面時,頁面狀態不變,必須在unLoad時手動重置狀態等
-
mpvue 會封裝小程序數據對象,通常以$mp開頭,如event.$mp.detail.target等
-
小程序的組件和vue組件有差異,不要幻想vue組件的特性都能用,如slot,異步組件等等
-
vue store 和 wx localstorage 最好不要弄混,要根據不同需要選擇不同的存儲方式
-
不要用vue路由,要采用小程序原生的導航機制
然后,我們搭建開發環境,mpvue腳手架是開箱即用的:
# 全局安裝 vue-cli # 一般是要 sudo 權限的 $ npm install --global vue-cli@2.9# 創建一個基于 mpvue-quickstart 模板的新項目 # 新手一路回車選擇默認就可以了 $ vue init mpvue/mpvue-quickstart my-project# 安裝依賴,走你 $ cd my-project $ npm install $ npm run dev接著,完善文件結構,增加 config、store、mixins等模塊,如圖:
app.json是小程序專用文件,也需完善下:
{"pages": ["pages/citylist/main","pages/citydetail/main"],"permission": {"scope.userLocation": {"desc": "你的位置信息將用于小程序位置接口的效果展示"}},"window": {"backgroundTextStyle": "light","navigationBarBackgroundColor": "#eee","navigationBarTitleText": "全球地鐵,全程為你","navigationBarTextStyle": "black"} }然后就可以愉快的寫Vue代碼了,咔咔一個頁面,咔咔又是一個頁面,組件,store,數據驅動,你喜歡的樣子,它都有。
騰訊地圖+ 小程序
著重說一下地圖的接入,騰訊地圖提供了兩個對接入口給小程序,1是個性化地圖展示,2是專用SDK,二者共同完善了小程序的地圖生態。
1、個性地圖展示需要開發者自行注冊并申請開發者密鑰(key),并在管理后臺綁定小程序,然后設置個性地圖的樣式,才能使用:
<mapid="citymap"name="citymap":longitude="lng":latitude="lat":polyline="polyline":markers="markers"scale="12":subkey="YOUR_OWN_QQMAP_KEY"show-locationshow-compassenable-rotatestyle="width: 100%; height: 100%;" ><cover-view class="map-cover-view"><button class="explore-btn" type="primary" @tap="exploreCity">查看旅游攻略</button></cover-view> </map>其中,map是小程序的原生組件,原生組件脫離在 WebView 渲染流程外,它的層級是最高的,所以頁面中的其他組件無論設置 z-index 為多少,都無法蓋在原生組件上。說白了就是原生組件是微信客戶端提供的,它不屬于內置瀏覽器,為此,小程序專門提供了 cover-view 和 cover-image 組件,可以覆蓋在部分原生組件上面。這兩個組件也是原生組件,但是使用限制與其他原生組件有所不同。
筆者就因為這個坑耽誤了不少時間,有時候開發工具可以用,但到了真機上組件就完全亂了,所以還是要以真機調試為準。對于原生組件,不要用太復雜的css,它的很多css屬性支持的都不好。
map可以定義多個參數,經緯度不用說,scale指放縮比例,也就是地圖比例尺,polyline在地圖上繪制折線,markers用于標記地圖上的點,show-location用于顯示用戶所在位置,show-compass顯示指北針。
2、專用SDK,目前提供這些能力:
-
search(options:Object) 地點搜索,搜索周邊poi,比如:“酒店” “餐飲” “娛樂” “學校” 等等
-
getSuggestion(options:Object) 用于獲取輸入關鍵字的補完與提示,幫助用戶快速輸入
-
reverseGeocoder(options:Object) 提供由坐標到坐標所在位置的文字描述的轉換。輸入坐標返回地理位置信息和附近poi列表
-
geocoder(options:Object) 提供由地址描述到所述位置坐標的轉換,與逆地址解析的過程正好相反
-
direction(options:Object) 提供駕車,步行,騎行,公交的路線規劃能力
-
getCityList() 獲取全國城市列表數據
-
getDistrictByCityId(options:Object) 通過城市ID返回城市下的區縣
-
calculateDistance(options:Object) 計算一個點到多點的步行、駕車距離
我們以公共交通路線規劃為例來看下(以下代碼經過簡化處理):
第一步,初始化地圖SDK對象
import config from '@/config' import QQMapWX from '../../assets/lib/qqmap-wx-jssdk.js' // 這里用未壓縮版的代碼 const QQMapSDK = new QQMapWX({key: config.qqMapKey || '' })第二步,獲取起止坐標點,并進行路線查詢
// 坐標從上一頁query傳進來,坐標為浮點數,可通過geocoder接口獲取 this.fromLocation = {latitude: +query.from.split(',')[0] || -1,longitude: +query.from.split(',')[1] || -1 }this.toLocation = {latitude: +query.to.split(',')[0] || -1,longitude: +query.to.split(',')[1] || -1 }// 查詢地圖路線 queryMapRoutine() {QQMapSDK.direction({mode: 'transit', // 'transit'(公交路線規劃)// from參數不填默認當前地址from: this.fromLocation,to: this.toLocation,success: (res) => {console.log('路線規劃結果', res);let routes = res.result.routes;this.routes = routes.map(r => {// 對每一種路線方案,分別進行解析return this.parseRoute(r)})console.log('parsed routes', this.routes)}}) }第三步,路線解析,生成路線描述等
// 解析路線,包括距離,時間,描述,路線,起止點等 parseRoute(route) {let result = {}// 出發時間result.setOutTime = formatTime(new Date())result.distance = route.distance < 1000 ?`${route.distance}米` :`${(route.distance / 1000).toFixed(2)}公里`result.duration = route.duration < 60 ?`${route.duration}分鐘` :`${parseInt(route.duration / 60)}小時${route.duration % 60}分鐘`result.desc = []// 每一個路線分很多步,如先步行,后乘公交,再搭地鐵等route.steps.forEach(step => {// if (step.mode == 'WALKING' && step.distance > 0) {// result.desc.push(`向${step.direction}步行${step.distance}米`)// }if (step.mode == 'TRANSIT' && step.lines[0]) {let line = step.lines[0]if (line.vehicle == 'BUS') line.title = `公交車-${line.title}`if (line.vehicle == 'RAIL') line.title = `鐵路`result.desc.push(`${line.title}: ${line.geton.title} —> ${line.getoff.title},途經 ${line.station_count} 站。`)}})result.polyline = []result.points = []//獲取各個步驟的polyline,也就是路線圖for(let i = 0; i < route.steps.length; i++) {let step = route.steps[i]let polyline = this.getStepPolyline(step)if (polyline) {result.points = result.points.concat(polyline.points)result.polyline.push(polyline)}}// 標記路線整體顯示坐標this.getStepPolyline.colorIndex = 0let midPointIndex = Math.floor(result.points.length / 2)result.latitude = result.points[midPointIndex].latituderesult.longitude = result.points[midPointIndex].longitude// 標記路線起止點let startPoint = result.points[0]let endPoint = result.points[result.points.length - 1]result.markers = [{iconPath: this.startIcon,id: 0,latitude: startPoint.latitude,longitude: startPoint.longitude,width: 28,height: 28,zIndex: -1,anchor: {x: 0.5, y: 1}},{iconPath: this.endIcon,id: 1,latitude: endPoint.latitude,longitude: endPoint.longitude,width: 28,height: 28,zIndex: -1,anchor: {x: 0.5, y: 1}}]return result },第四步,getStepPolyline函數 獲取路線每一步的路線polyline
getStepPolyline(step) {let coors = [];// 隨機顏色let colorArr = ['#1aad19', '#10aeff', '#d84e43']let _dottedLine = trueif (step.mode == 'WALKING' && step.polyline) {coors.push(step.polyline);_dottedLine = false} else if (step.mode == 'TRANSIT' && step.lines[0].polyline) {coors.push(step.lines[0].polyline);} else {return null}//坐標解壓(返回的點串坐標,通過前向差分進行壓縮)let kr = 1000000;for (let i = 0 ; i < coors.length; i++){for (let j = 2; j < coors[i].length; j++) {coors[i][j] = Number(coors[i][j - 2]) + Number(coors[i][j]) / kr;}}//定義新數組,將coors中的數組合并為一個數組let coorsArr = [];let _points = [];for (let i = 0 ; i < coors.length; i ++){coorsArr = coorsArr.concat(coors[i]);}//將解壓后的坐標放入點串數組_points中for (let i = 0; i < coorsArr.length; i += 2) {_points.push({ latitude: coorsArr[i], longitude: coorsArr[i + 1] })}if (!this.getStepPolyline.colorIndex) {this.getStepPolyline.colorIndex = 0}let colorIndex = this.getStepPolyline.colorIndex % colorArr.lengththis.getStepPolyline.colorIndex++// 最終polyline結果let polyline = {width: 7,points: _points,color: colorArr[colorIndex],dottedLine: _dottedLine,arrowLine: true, // 帶箭頭的線, 開發者工具暫不支持該屬性borderColor: '#fff',borderWidth: 1}return polyline }最后,綁定到地圖上并輸出,我們可以得到一個大致這樣的結果:
廣州火車站 -> 廣州塔 9.88km 30分鐘 地鐵5號線 廣州火車站 -> 珠江新城,途徑7站 地鐵3號線 珠江新城 -> 廣州塔,途徑1站這樣我們就通過direction接口進行了簡單的路線規劃功能,接著把生成的數據綁定到地圖組件上,一個簡易的小程序就做好了,是不是很簡單?當然如果想做得更好,就要調用其他相似接口,慢慢完善細節。
<mapid="citymap"name="citymap":latitude="currentRoute.latitude":longitude="currentRoute.longitude":polyline="currentRoute.polyline":markers="currentRoute.markers"scale="12":subkey="qqMapKey"show-locationshow-compassenable-rotatestyle="width: 100%; height: 100%;" ></map>效果
作者:棱鏡_jh
鏈接:https://juejin.cn/post/6844903809420886029
來源:掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
總結
以上是生活随笔為你收集整理的微信小程序 + 腾讯位置服务SDK 实现路线规划的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: crx插件转换火狐插件_关于Firefo
- 下一篇: python中counter怎么用_带你