📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗
🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数,欢迎多多交流。👍
文章目录
- 写在前面的话
- 海报生成
- 需求简介
- 地图组件介绍
- 后台位置共享
- 足迹绘制
- 选点绘制
- 其他功能
- 总结陈词
写在前面的话
本篇文章是微信小程序系列的第四篇,本着介绍地图导航小程序的核心地图功能。
相关文章
《微信小程序实战(1)· 开篇示例 》
《微信小程序实战(2) · 组件封装》
《微信小程序实战(3) · 推广海报制作》
海报生成
需求简介
要求实现微信小程序的地图功能清单如下:
1、用户可以共享位置信息,也可以看见他人的位置信息;
2、移动过程中要可以描绘足迹,同时保存后可以查看;
3、地图支持选点画线功能,同样支持保存分享;
上述三个需求点,分别对应地图的三个功能,下面一一展开。
地图组件介绍
微信小程序的地图组件是一个非常实用的功能,允许开发者在小程序中嵌入地图,展示地理位置、标记点、路线等信息。
1、地图组件基本用法
在小程序的 WXML 文件中使用 <map>
标签来创建地图组件:
<map longitude="{{longitude}}" latitude="{{latitude}}" scale="14" markers="{{markers}}" />
2、主要属性
longitude: 地图中心的经度。
latitude: 地图中心的纬度。
scale: 地图缩放级别,范围通常是 5 到 18。
markers: 地图上的标记点,通常是一个数组,包含多个标记的经纬度和其他信息。
3、标记点(Markers)
标记点是地图上显示的位置,可以通过设置 markers 属性来添加。每个标记点是一个对象,包含以下属性:
latitude: 标记点的纬度。
longitude: 标记点的经度。
title: 标记点的标题。
iconPath: 自定义标记图标的路径。
width: 图标的宽度。
height: 图标的高度。
this.setData({
markers: [{
id: 1,
latitude: 23.099994,
longitude: 113.324520,
title: '标记点1',
iconPath: '/images/marker.png',
width: 50,
height: 50
}]
});
4、事件处理
地图组件支持多种事件,例如:
regionchange: 地图区域变化时触发。
markertap: 点击标记点时触发。
maptap: 点击地图时触发。
<map bindmarkertap="onMarkerTap" bindregionchange="onRegionChange" />
onMarkerTap(e) {
console.log('点击了标记点', e.markerId);
},
onRegionChange(e) {
console.log('地图区域变化', e.type);
}
5、获取用户位置
可以使用微信小程序的 API 获取用户的地理位置,并将其设置为地图的中心:
wx.getLocation({
type: 'wgs84',
success: (res) => {
this.setData({
latitude: res.latitude,
longitude: res.longitude
});
}
});
后台位置共享
前面介绍的都是基础用法,比较简单,可忽略,接下来开始正篇。
这个需求要拆解为两个部分:
1、共享自己的位置(上传位置信息);
2、显示所有人的位置(定时获取);
先看第一点,要共享自己的位置,同时要支持微信小程序切换至后台,仍然可以监听到位置变化。
需要借助小程序的onLocationChange
支持位置变更,先看示例代码。
openLocationHandle() {
let that = this
wx.getSetting({
success(res) {
if (res.authSetting['scope.userLocationBackground']) {
that.startLocationUpdateBackground()
app.globalData.hasStart = true
} else {
wx.authorize({
scope: 'scope.userLocationBackground', success() {
that.startLocationUpdateBackground()
app.globalData.hasStart = true
}, fail(err) {
console.log('userLocationBackground失败,错误信息:', err)
that.openSetting()
}
})
}
}
})
},
/**
* 位置处理 - 开启小程序监听动作
*/
startLocationUpdateBackground: function () {
let that = this
wx.setStorageSync('oldLocation', -1);
wx.setStorageSync('oldTime', -1);
// 开启小程序在前后台时均可接收位置消息
wx.startLocationUpdateBackground({
type: 'gcj02', success: function () {
// 监听实时地理位置变化事件
// 需结合 wx.startLocationUpdateBackground、wx.startLocationUpdate使用
wx.onLocationChange(that.onLocationChangeHandle)
}, fail: function (err) {
ace.msg('startLocation失败')
console.log('startLocationUpdateBackground失败,错误信息:', err)
that.openSetting()
},
})
},
首先,先授权一下scope.userLocationBackground
后台监听权限,授权成功则可以调用wx.startLocationUpdateBackground
打开后台位置变化监听功能,同时使用wx.onLocationChange
监听微信变化,传入的回调函数里面可以将获取到的位置信息,不断上报。
要使用后台授权功能,app.json还需要添加配置如下,按需添加需要的API即可。
"requiredPrivateInfos": [
"getLocation",
"chooseAddress",
"onLocationChange",
"startLocationUpdate",
"startLocationUpdateBackground"
]
核心的onLocationChangeHandle逻辑里面,可以将回传的经纬度不断上报到后端,部分代码如下。
下方代码可以通过位置变化和坐标变化幅度判断,避免频繁处理请求(还不够的话可以添加距离变化判断)。
onLocationChangeHandle: function (res) {
let {
latitude, longitude
} = res
//省略部分逻辑
。。。
// 获取上次保存的位置信息
let oldLocation = wx.getStorageSync('oldLocation')
// 获取这次获取的位置信息
let nowLocation = latitude + ',' + longitude
// 位置一样则退出,坐标没变化
if (nowLocation === oldLocation) {
return;
}
// 获取上次执行的时间
let oldTime = wx.getStorageSync('oldTime')
// 获取当前时间
let currentTime = new Date().getTime()
// 间隔时间小于6S退出
if (!oldTime || currentTime - oldTime < 6000) {
return;
}
// 上传位置信息,调后端逻辑
。。。
// 修改缓存数据
wx.setStorageSync('oldLocation', nowLocation);
wx.setStorageSync('oldTime', currentTime);
}
第二个点就简单多了,就写一个定时器,然后不断获取位置,利用map组件的标记功能即可。
核心代码如下:
// 定时获取所有人的实时位置
that.timeHandleGet();
shareIntervalNum = setInterval(function () {
that.timeHandleGet();
}, 2000);
timeHandleGet() {
let that = this
let payNo = that.data.payNo
// 获取其他在线用户的位置
ace.sendGet('xjStaffDict/locationShareList', function (data) {
let newArr = [] //所有人的标记信息
data.forEach(function (v, i) {
// 非本人则渲染共享标记信息
if (v.remark && v.staffId !== payNo) {
let nowPositionArr = v.remark.split(',')
let tempMark = that.markHandle("位置共享", nowPositionArr[1], nowPositionArr[0], v.realyName, "", i, v.staffId, v.realyImg);
tempMark.payNo = v.staffId
newArr.push(tempMark)
}
})
that.setData({
markers: newArr
})
}, "no");
},
足迹绘制
足迹绘制也是基于第一个需求,自身位置不断变化的过程中,把经纬度暂存下来,然后利用map组件的polyline属性,绘制路线,部分代码如下:
// 路线信息拼接
points.push({longitude: longitude, latitude: latitude})
let polyline = [{
points: points, color: "#FF0000DD", width: 2, dottedLine: false
}];
//更新路线和自己的坐标
that.setData({
longitude: longitude, latitude: latitude
})
if (points.length > 1) {
that.setData({
polyline: polyline
})
}
ace.msg('逻辑成功,节点数:' + points.length);
//放入缓存,后续加载
wx.setStorageSync('pointsData', JSON.stringify(points));
过程示例图如下:
足迹保存后查看效果如下:
选点绘制
这项功能就更简单了,利用map组件的地图坐标点击监听方法bindtap实现。
部分代码如下:
mapClick(e) {
let that = this;
let pointHandleFlag = that.data.pointHandleFlag || false
if (pointHandleFlag) {
//获取当前地图选点
let markers = that.data.markers;
let id = ace.generateUUID();
let name = `选点${markers.length + 1}`
let tempMark = that.markHandle('选点', e.detail.longitude, e.detail.latitude, '', name, markers.length, id);
points.push(e.detail)
markers.push(tempMark)
if (points.length > 1) {
let polyline = [{
points: points, color: "rgba(5,197,95,0.87)", width: 2, dottedLine: false
}];
that.setData({
markers, polyline
})
} else {
that.setData({
markers
})
}
} else {
console.log('当前非地图选点模式!')
}
},
示例图如下:
其他功能
有了前面marker的基础,想实现打标记功能就很简单了。
制作一个表单页面,如下所示:
创建完成后,将坐标信息在地图加载出来,也可以增加坐标过滤功能,或者增加点击展示详情。
总结陈词
此篇文章是《微信小程序实战》系列的第四篇,实际代码量较大,由于篇幅所限,没有贴出全部代码,主要学习一个地图功能思想,感兴趣的可以留言交流,希望可以帮助到大家。
💗 后续会逐步分享企业实际开发中的实战经验,有需要交流的可以联系博主。