原文連接css
最近小程序的發展愈來愈火了,做爲各個產品線的extra服務入口,以輕便、快速、強大的社交鏈吸引着大量的用戶和開發者。業內開發框架層出不窮,wepy,mpvue,taro等等,都在朝着更快,更強大的方向發展,有統一 H五、微信、支付寶、百度和頭條小程序的大趨勢。html
本文旨在以mpvue框架爲基礎,探討地圖類小程序的開發思路,權當分享和總結。 筆者利用mpvue + 騰訊地圖的能力作了一個地鐵路線規劃的小程序,主要提供全球主要城市的地鐵線網圖及旅遊介紹,其中國內城市支持查看地圖和路線規劃。雖然功能並不複雜,但也算一個實用工具了。話很少說,先體驗一下:vue
github源碼地址: github.com/WarpPrism/S…webpack
下面就開始正式介紹如何開發了:git
mpvue = miniprogram + vue framework,說白了就是用vue框架開發小程序。mpvue最近升級爲2.x版本,支持微信、支付寶、百度和頭條小程序。和傳統方式相比,mpvue開發具備如下優勢:github
就我的使用體驗來看,仍是挺絲滑順暢的,傳統web應用開發無縫切換至小程序開發,基本零門檻。要注意的就是小程序的限制及和vue的差別:web
$mp
開頭,如event.$mp.detail.target
等而後,咱們搭建開發環境,mpvue腳手架是開箱即用的:vue-cli
# 全局安裝 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等模塊,如圖:npm
app.json是小程序專用文件,也需完善下: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),並在管理後臺綁定小程序,而後設置個性地圖的樣式,才能使用:
<map id="citymap" name="citymap" :longitude="lng" :latitude="lat" :polyline="polyline" :markers="markers" scale="12" :subkey="YOUR_OWN_QQMAP_KEY" show-location show-compass enable-rotate style="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,目前提供這些能力:
咱們以公共交通路線規劃爲例來看下(如下代碼通過簡化處理):
第一步,初始化地圖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 = 0
let midPointIndex = Math.floor(result.points.length / 2)
result.latitude = result.points[midPointIndex].latitude
result.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 = true
if (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.length
this.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接口進行了簡單的路線規劃功能,接着把生成的數據綁定到地圖組件上,一個簡易的小程序就作好了,是否是很簡單?固然若是想作得更好,就要調用其餘類似接口,慢慢完善細節。
<map id="citymap" name="citymap" :latitude="currentRoute.latitude" :longitude="currentRoute.longitude" :polyline="currentRoute.polyline" :markers="currentRoute.markers" scale="12" :subkey="qqMapKey" show-location show-compass enable-rotate style="width: 100%; height: 100%;" ></map>
複製代碼
更多實現請參照源碼和小程序自己,若是對你有幫助,能夠star支持。
這裏還有一款鋼琴教學
類的 web應用,發佈在gitee page上
crystalworld.gitee.io/qpiano/#/
感興趣的朋友能夠看下,以後有時間筆者會補上開發教程和源碼,另做分享。
2019-04-01更新: 介紹文章傳送門: juejin.im/post/5ca1d2…