前端根据起始点经纬度生成路径的GPS集合

1,069 阅读2分钟

有这样一个需求,输入起始点和终点经纬度,在地图上模拟一条路径出来。因为没有真实的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');
})

image.png

三、后续

优化以上代码,本地测试完后部署