2

使用高德地图js api 自动画出电子围栏
因直接画多边形不太准确,需要沿路来画围栏

电子围栏思路:

1. 找到原点经纬度 x

const CENTER = [116.397504,39.89619]  
const DISTANCE = 300  //单位m  

const map = new AMap.Map("container", {
    center: CENTER,
    zoom: 14
});
2. 根据x点在地图上画出一个圆
const circle = new AMap.Circle({
    center: CENTER,
    radius: DISTANCE, //半径
    borderWeight: 3,
    strokeColor: "#FF33FF", 
    strokeOpacity: 1,
    strokeWeight: 6,
    strokeOpacity: 0.2,
    fillOpacity: 0.4,
    strokeStyle: 'dashed',
    strokeDasharray: [10, 10], 
    fillColor: '#1791fc',
    zIndex: 50
})
circle.setMap(map)
// 缩放地图到合适的视野级别
map.setFitView([ circle ])

参考:
https://lbs.amap.com/api/java...

3. 在圆边线上 分别找到向 东、东南、南、西南、西、西北、北、东北 8个方向的位置

得到 x1,y1 ~ x8,y8 ,8个 位置的 经纬度,定义为 A1 ~ A8 的坐标

先根据圆的公式,找到圆上的各点,再用各点转换成地图的经纬度

/**
 * 
 * 获取圆上的点(步长 45度)
 *
 **/
function setCirclePoint(centerpoint = CENTER, radius = DISTANCE) {
    const r = 6371000;   //地球的平均半径
    const numpoints = 360;
    const phase = 2 * Math.PI / numpoints;
    let pointArr = []

    //画点
    for (let i = 0; i < numpoints; i+=45) {
        // 计算坐标点
        let dx = (radius * Math.cos(i * phase));
        let dy = (radius * Math.sin(i * phase));
        
        // 转换成经纬度
        let dlng = dx / (r * Math.cos(centerpoint.lat * Math.PI / 180) * Math.PI / 180);
        let dlat = dy / (r * Math.PI / 180);
        let newlng = centerpoint.lng + dlng;
        let newlag = centerpoint.lat + dlat;
        pointArr.push([newlng,newlag])

        // 实例化点标记
        const marker = new AMap.Marker({
            position: [newlng, newlag],
            icon: startIcon,
            offset: new AMap.Pixel(-13, -30)
        });
        markers.push(marker);
        marker.setMap(map);
    }
    return pointArr
}

如图:

参考:
https://blog.csdn.net/jinshit...
https://blog.csdn.net/Dust_Ev...
https://lbs.amap.com/api/andr...

4. 搜索 A1 ~ A8 8个坐标最近的 POI点,A1 = “国贸三期”,A2 = “东直门”,A3 = “奥体森林公园”。。。。类推
// 高德地图查询周边
    function aMapSearchNearBy(centerPoint) {
        return new Promise((resolve,reject)=>{
            AMap.service(["AMap.PlaceSearch"], () => {
                const placeSearch = new AMap.PlaceSearch({
                    pageSize: 10,    // 每页10条
                    pageIndex: 1,    // 获取第一页
                });

                // 第一个参数是关键字,这里传入的空表示不需要根据关键字过滤
                // 第二个参数是经纬度,数组类型
                // 第三个参数是半径,周边的范围
                // 第四个参数为回调函数
                placeSearch.searchNearBy('', centerPoint, 1000, (status, result) => {
                    if(result.info === 'OK') {
                        const locationList = result.poiList.pois; // 周边地标建筑列表
                        resolve(locationList[0])
                        
                    } else {
                        console.log('获取位置信息失败!');
                        reject()
                    }
                });
            });
        })
    }

因必须是A1-A8顺序返回POI结果,高德API为异步,所以使用Promise进行同步处理

//获取POI信息
const POIArr = await Promise.all(points.map(async (item)=>{
    return await aMapSearchNearBy(item)
}))

参考:
https://lbs.amap.com/api/java...

5. 将这8个POI点依次相连(A1-A2,A2-A3,A3-A4,...A8-A1)用导航路径画出 (步行),得到 L1 ~ L8 这 8条路径
   /**
     * 绘制路线(步行)
    */
    function drawWalk(data, i){
        return new Promise((resolve,reject)=>{
            //步行导航
            const walking = new AMap.Walking({
                map: map,
                panel: "panel",
                hideMarkers: true,   //设置隐藏路径规划的起始点图标
            }); 

            let start = [POIArr[i].location.lng, POIArr[i].location.lat]
            let end = i === POIArr.length-1 ? [POIArr[0].location.lng, POIArr[0].location.lat] : [POIArr[i+1].location.lng, POIArr[i+1].location.lat]
            

            //根据起终点坐标规划步行路线
            walking.search(start, end, (status, result) => {
                resolve(result)
                if (status === 'complete') {
                    log.success('绘制步行路线完成')
                } else {
                    log.error('步行路线数据查询失败' + result)
                } 
            });
        });
    }

依次画出步行路径

const walkRes = await Promise.all(POIArr.map(async (item, index)=>{
    return await drawWalk(item, index)
}))

如图:


参考:
https://lbs.amap.com/api/java...

6. 存储8条路线的拐点

根据各步行路径返回的信息找到路的拐点,并保存起来,保存之前需要去重。

    walkRes.map((key)=>{
        const steps = key.routes[0].steps
        steps.map((item, index)=>{
            item.path.map((pos)=>{
                formatData(pos)
            })
        })
    })

7. 验证保存的拐点数据,画出的多边形是否和路线一致

第一次取的值为steps属性下的start_location,但出如下图


但不是沿路的,也缺失了一些拐点

第二次取steps下的path中的路线,搞定

8. 完成。

注:代码不全,仅供参考


0_10_10_10_1
100 声望0 粉丝