【黄啊码】微信小程序外卖项目显示骑手位置

2022-01-09 09:35:03 浏览数 (1)

小demo,不太建议完全照抄,需要的可以在上边完成拓展,不喜勿喷!!!

这个功能最重要的就是路线规划,路线两端分别是点外卖的人,商家,送外卖的骑手,商家的位置,后端接口直接就能拿到给前端,而用户的位置,由于地址是自己填的,因此前端也可以轻松的拿到地址转为经纬度。那骑手的位置呢?这就要从第三方物流接口去获取了,那得看实际的项目接入的是顺丰,美团还是哒哒或者其他什么。而且这个小demo也不需要那么复杂,虽然没有骑手位置,那就简单模拟一下好了。首先在小程序上创建一张地图出来:

代码语言:javascript复制
<view class="map-container">
   <map class="gaode-map" id="map" markers="{{markers}}" longitude="{{longitude}}" polyline="{{polyline}}" latitude="{{latitude}}" scale="14"></map>
</view>

css

代码语言:javascript复制
 page,html,body {
   width:100%;
   height:100%;
 }
 .map-container {
   width:100%;
   height:100%;
 }
 
 .gaode-map {
   width:100%;
   height:100%;
 }

js文件

代码语言:javascript复制
const gaodeMap = require('../../amap-wx.js'); // 引入高德sdk
 const map = new gaodeMap.AMapWX({
   key: 'xxxxxxxx' // 高德申请的key
 });
 Page({
   data: {
     longitude: 116.397128, // 给个默认的经纬度 定位到北京天安门
     latitude: 39.916527, //
     distance: 0, // 骑手距离
     cost: 0, // 大概时间
     polyline: [], // 存放路线的经纬度
     markers: [{ // 自己设置的三个mark标记,分别是 商家,用户,骑手
       iconPath: "/images/shangjia.png",
       id: 0,
       latitude: 39.916527,
       longitude: 116.397128,
       width: 20,
       height: 23
     }, {
       iconPath: "/images/weizhi.png",
       id: 1,
       latitude: 31.23035,
       longitude: 121.473717,
       width: 20,
       height: 23
     }, {
       iconPath: "/images/qishou.png",
       id: 2,
       latitude: 31.23035,
       longitude: 121.473717,
       width: 20,
       height: 23
     }],
   },
 
   // 获取用户位置信息
   getUserLocation() {
     let that = this
     wx.getLocation({
       success: (res) => {
         that.setData({
           longitude: res.longitude,
           latitude: res.latitude,
           ['markers[0].latitude']: res.latitude,
           ['markers[0].longitude']: res.longitude
         }, () => {
           map.getRidingRoute({
             origin: '121.473717,31.23035', // 路线规划的起点 随便在我附近搜的位置转的经纬度
             destination: `${res.longitude},${res.latitude}`, // 目的地经纬度
             success: (data) => {
               let points = [];
               let distance = 0
               let cost = 0
               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])
                     })
                   }
                 }
               }
 
               if (data.paths[0] && data.paths[0].distance) {
                 distance = data.paths[0].distance   '米'
               }
               if (data.paths[0] && data.paths[0].duration) {
                 cost = parseInt(data.paths[0].duration / 60)   '分钟'
               }
 
               that.setData({
                 polyline: [{
                   points: points,
                   color: "#0091ff",
                   width: 6
                 }],
                 distance,
                 cost,
                 ['markers[2].longitude']: points[120].longitude,
                 ['markers[2].latitude']: points[120].latitude
               })
               
               let tempNum = 0
               // 设置一个定时器根据路线规划上的经纬度每100毫秒前进一步
              let timer = setInterval(()=>{
                 if(tempNum >= points.length){
                   // 跑完了规划路线就停止
                   clearInterval(this.data.timer)
                 }
                 if(!this.data.timer){
                   // 将定时器设置为全局的,方便退出组件时销毁
                   this.setData({
                     timer:timer
                   })
                 }
                 // 
                 this.setData({
                   ['markers[2].longitude']: points[  tempNum].longitude,
                   ['markers[2].latitude']: points[  tempNum].latitude
                 })
               },100)
             }
           })
         })
       },
     })
   },
 
   // 用户授权
   userAuth() {
     wx.getSetting({
       success: (res) => {
         if (!res.authSetting['scope.userLocation']) {
           wx.authorize({
             scope: 'scope.userLocation',
             success: () => {
               // 同意授权位置
               this.getUserLocation()
             },
             fail: () => {
               wx.showModal({
                 content: '拒绝授权将无法获取您的位置,请授权。',
                 showCancel: false,
                 success: (r) => {
                   if (r.confirm) {
                     // 打开设置页面让用户手动开启权限
                     wx.openSetting({
                       success:(v)=>{
 
                       }
                     })
                   }
                 }
               })
             }
           })
         }
       },
     })
   },
 
   onLoad: function () {
   },
 
   onShow:function(){
     this.userAuth()
   },
 
   onUnload:function(){
     clearInterval(this.data.timer)
   }
 
 })

s文件50行之下的那段代码是直接从高德文档copy过来的,顺便修改了一下。当调用高德的getRidingRoute函数之后,传入两个点的经纬度,他会返回一长串数组形式的经纬度给我们:

polyline就是我们需要的路线的经纬度,在代码中经过for循环去取出经纬度计算,就可以拿到预计达到时间以及路程长短,这个计算并不难,而且高德文档本身就有,上面那段计算的代码就是现成的。为了模拟出那个骑手移动的效果,我在下面加了一个定时器,每100毫秒让电动车图标根据路线的经纬度移动一下,但实际情况的话,骑手的位置应该是由其他接口给前端才对,这里只是为了看看效果,仅此而已。地图上的那条路线,只是用来给用户看的而已,因为别人在送外卖的时候,不止送一份,还会去给别人,因此在地图上获取骑手位置的时候,人家可能压根不在那条线上,也可能是走其他小路穿插,这都是正常的。还有就是骑手的位置也并非实时更新,我看美团的好像就不是实时更新,而是隔一段时间更新一次,前端做个轮询就好了,简单粗暴。以上代码示例并非真实项目,只是为了看实现效果写的小示例而已。

0 人点赞