微信小程式—製作一個簡單的跑步小程式

語言: CN / TW / HK

theme: channing-cyan

我正在參加「掘金·啟航計劃」

準備工作

1.微信公眾平臺註冊一個小程式賬號,註冊完之後左邊選單列表點選開發管理->開發設定,就可以看到自己的appid(小程式id)了

image.png

2.官網安裝微信開發者工具

image.png

建立專案

1.建立小程式專案

開啟微信開發者工具選擇建立小程式,輸入專案名稱,目錄自定義,將appid複製進AppID裡,點選建立

image.png

2.初始化小程式專案

這是新建立好的小程式目錄,裡面非常多檔案是不需要的,我們要刪除多餘的檔案

image.png

這是刪除好的檔案目錄,可以看到簡潔很多了

image.png

pages資料夾是存放頁面的資料夾,右擊新建index資料夾,再右擊新建Page自動建立js,json,wxml,wxss檔案

  • .js 裡面編寫一些生命週期鉤子,事件處理,全域性資料…
  • .json 裡面編寫一些頁面配置,頁面的 .json 配置會覆蓋 app.json 的配置
  • .wxml 裡面編寫一些頁面內容,UI標籤,資料繫結
  • .wxss 裡面編寫一些樣式

json檔案裡新增navigationBarTitleText設定導航欄標題

image.png

匯入一張紅色圓點的圖片用作跑步時的定位標記

hd.png

開始編寫

1.wxml

建立四個按鈕分別用作開始記錄/暫停記錄,清除資料,儲存資料,回放,並建立對應的方法

<view class="header"> <button type="primary" size="mini" bindtap="run">{{running?'暫停記錄':'開始記錄'}}</button> <button type="warn" size="mini" bindtap="clear">清除資料</button> <button type="default" size="mini" bindtap="save">儲存資料</button> <button type="primary" size="mini" bindtap="translateMarker">回放</button> </view> 建立text標籤用作記錄里程和時間

<view class="counter"> <text>里程:{{mdl.formatKM(meters)}} 時間: {{mdl.formatTime(seconds)}}</text> </view> 使用小程式官方內建的map地圖元件,裡面有好幾十個屬性,但我們具體只使用一下幾個屬性: - latitude:number型別,中心緯度 - longitude:number型別,中心經度 - markers:array型別,標記點 - polyline:array型別,路線

```

```

2.wxss

.header{ display: flex; } .counter{ text-align: center; } .map{ width: 100%; height: 90vh; }

3.js

js檔案為我們建立好了一些生命週期函式,但是看起來太亂了

image.png

直接ctrl+a全選刪除,再把page添加回去,dada裡初始一些資料

Page({ data:{ meters:0,//里程 seconds:0,//時間 latitude:0,//緯度 longitude:0,//經度 running:false,//是否開始 interval:1000,//多少秒獲取當前定位 markers:[],//標記 polyline:[],//路線 point:[],//標註 i:0, ii:0 } }) 進入小程式在onLoad生命週期裡獲取當前位置,onReady裡設定map地圖上下文

onReady:function () { //MapContext 例項,可通過wx.createMapContext獲取,通過 `id` 跟一個map元件繫結,操作對應的map元件 this.mapCtx = wx.createMapContext('map') }, onLoad(){ this.curLocation() }, curLocation(){ //wx.getLocation獲取當前的地理位置,type設定'gcj02'返回gps座標 wx.getLocation({ type: 'gcj02', }).then(res=>{ console.log(res) let{latitude,longitude}=res this.setData({ latitude,longitude }) }) }, 這樣地圖就可以顯示出來了

image.png

在點選開始記錄按鈕來記錄資料前新建一個utils.js檔案用於計算距離並向外匯出,在index.js裡引入

``` //index.js const utils=require('utils')

//utils.js

//弧度 function toRadians(d){ return dMath.PI/180 } //利用兩點的經度,維度計算兩點距離 function getDistance(lat1,lng1,lat2,lng2){ const R=6378137 //赤道半徑 let dis=0 let deltaLat=toRadians(lat1)-toRadians(lat2) let deltaLng=toRadians(lng1)-toRadians(lng2) dis=2RMath.asin(Math.sqrt(Math.pow(Math.sin(deltaLat/2),2) +Math.cos(radLat1)Math.cos(radLat2)*Math.pow(Math.sin(deltaLng/2),2))) return dis } module.exports={ getDistance } ```

然後可以點選開始按鈕進行記錄資料了,在onLoad裡新增一個定時器用於記錄資料

onLoad(){ this.curLocation() setInterval(this.record,this.data.interval) }, run(){ this.setData({ running:!this.data.running }) }, record(){ //沒有開始記錄return出去 if(!this.data.running){ return } this.setData({ seconds:this.data.seconds+this.data.interval/1000 }) wx.getLocation({ type: 'gcj02', }).then(res=>{ //當前標記位置資訊 let newMarker={ latitude:res.latitude, longitude:res.longitude, iconPath:'hd.png', width:12, height:12, id:1+this.data.i } let i=this.data.i let point=this.data.point let pace=0 let markers=this.data.markers if(this.data.markers.length>0){ let lastmarker=this.data.markers.slice(-1)[0] //根據上一次標記點和當前標記點計算距離,超出15m新增標記,否則視為距離太短不新增標記 pace=utils.getDistance(lastmarker.latitude,lastmarker.longitude, newMarker.latitude,newMarker.longitude) if(pace>15){ markers.push(newMarker) i=this.data.i+1 point.push({longitude:res.longitude,latitude:res.latitude}) }else{ pace=10 } }else{ markers.push(newMarker) i=this.data.i+1 point.push({longitude:res.longitude,latitude:res.latitude}) } this.setData({ latitude:res.latitude, longitude:res.longitude, markers, point, meters:this.data.meters+pace, i }) }) }, 然後出門走一圈記錄記錄😤😤😤

d59f3be5-d26b-4c61-9e82-665c9b11ecd5.gif

ok沒問題,然後下一個按鈕清除資料

clear(){ this.setData({ markers:[], meters:0, seconds:0, polyline:[], point:[], i:0, ii:0 }) }, 點選儲存資料按鈕時將資料新增進本地快取中

save(){ //沒有暫停記錄return出去 if(this.data.running){ return } let point=this.data.point let markers=this.data.markers //point新增陣列第一個陣列,回放線路時形成一個閉環 point.push(point[0]) markers.push(markers[0]) this.setData({ polyline:[{ points:point, color:'#99ff00', width:10, dottedLine:false }] }) wx.setStorage({ data:{ markers:this.data.markers, seconds:this.data.seconds, polyline:this.data.polyline, point:this.data.point, meters:this.data.meters }, key:'running', }).then(()=>{ wx.showToast({ title: '儲存成功', }) }) //本地快取後清理資料 this.clear() }, 點選回放按鈕,開始回放記錄

translateMarker() { let that=this //獲取本地快取 wx.getStorage({ key:'running', success:function (res) { console.log(res.data.markers) let running=res.data that.setData({ markers:running.markers, point:running.point, polyline:running.polyline, seconds:running.seconds, meters:running.meters }) } }) let ii=this.data.ii let markers=this.data.markers let markerId = markers[ii].id; let destination = { longitude: markers[ii+1].longitude, latitude: markers[ii+1].latitude }; //使每個不同距離的標記點勻速平移滑動,duration固定的話標記點距離不同動畫會時快時慢 let duration=utils.getDistance(markers[this.data.ii].latitude,markers[this.data.ii].longitude,markers[this.data.ii+1].latitude,markers[this.data.ii+1].longitude)*5 //回放使用MapContext.translateMarker this.mapCtx.translateMarker({ markerId: markerId,//當前標記點 destination: destination,//要移動到的下一個標記點 autoRotate: false,//關閉旋轉 duration: duration,//動畫市場 success(res) { that.setData({ ii: that.data.ii + 1 }); // 小於長度減1繼續下一個標記點動畫 if (that.data.ii < markers.length-1) { that.translateMarker(); } }, fail(err) { console.log('fail', err) } }) }

image.png

回放效果,動畫比較簡陋啊😛😛,可以自己設定樣式:

e3e897ca-2885-4877-9bf4-3d73db79ea03.gif