有这样一个需求,输入起始点和终点经纬度,在地图上模拟一条路径出来。因为没有真实的GPS点信息,所以你绘制出来的点,有可能是一条直线,如何让模拟出来的数据更逼真呢?本着划水不如前端自己研究的心理去实现
一、思路
- 拿到起始点,分别算出经纬度差值的绝对值,然后在绝对值内取点去分配,具体的分配方式可以参考微信的红包算法。这样会产生一个问题,颗粒度决定了直线的弯曲,要画足够多的点才能不是一条直线,于是加入正负数因子,根据起始点和重点经纬度算出这条轨迹的斜率,然后保持经度或者纬度一个数一直累加正数,一个数累加正负数因子和粒度的子程序算法产生的值……你会发现非常麻烦,而且并不真实
- 通过地图API进行导航路径规划,然后获取导航的路径的GPS点信息,你会发现轻松很多
二、实践
这里采用的是GCJ-02坐标系,因为高德地图和腾讯地图包括微信小程序都是用的这个坐标系,所以编写后使用会非常方便。可以参考以下文档
以高德地图为示例
1、先申请高德地图JSAPI拿到Key
2、查看数据结构进行编码
3、编写代码
npm i --save koa axios
const Koa = require('koa');
const axios = require('axios')
const key = '高德上申请的key';
let startLngLat = '';
let endLngLat = '';
let waypoints = ""; // 中间点,经度和纬度用","分割,经度在前,纬度在后,小数点后不超过6位,坐标点之间用";"分隔最大数目:16个坐标点。如果输入多个途径点,则按照用户输入的顺序进行路径规划
let url = '';
function setOps() {
url = `https://restapi.amap.com/v3/direction/driving?origin=${startLngLat}&destination=${endLngLat}&extensions=base&strategy=0&output=JSON&key=${key}`;
if (waypoints.length) {
url = url + '&waypoints' + waypoints
}
}
const app = new Koa();
async function getGPSFromAutoNavi() {
return new Promise((resolve, reject) => {
axios({
method: 'get',
url: url
}).then(res => {
if (res.status == 200) {
if (res.data.status == 1) {
let list = res.data?.route.paths[0]?.steps;
resolve(formatPolyline(list))
} else {
resolve({
status: res.data.status,
data: []
})
}
} else {
resolve({
status: -1,
data: []
})
}
})
})
}
function formatPolyline(list) {
let gpsList = [{
longitude: startLngLat.split(',')[0],
latitude: startLngLat.split(',')[1]
}]
list.forEach(item => {
let _list = item.polyline.split(';');
_list.forEach(_item => {
let _childList = _item.split(',')
let _obj = {
longitude: _childList[0],
latitude: _childList[1]
}
gpsList.push(_obj)
})
})
gpsList.push({
longitude: endLngLat.split(',')[0],
latitude: endLngLat.split(',')[1]
})
return {
status: 0,
data: gpsList
}
}
app.use(async (ctx) => {
let ctx_query = ctx.query;
startLngLat = ctx_query.startLngLat;
endLngLat = ctx_query.endLngLat;
waypoints = ctx_query.waypoints || '';
if (!startLngLat || !endLngLat) {
ctx.body = {
status: -1,
data: [],
msg:'参数错误'
}
return
}
console.log(ctx_query.startLngLat);
setOps();
ctx.body = await getGPSFromAutoNavi()
})
app.listen(8088, () => {
console.log('http://localhost:8088');
})
三、后续
优化以上代码,本地测试完后部署