微信小程序—制作一个简单的跑步小程序

语言: 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