高德地图画线搜索

397 阅读3分钟

画圈搜索

今天分享一下,使用高德地图api实现上图可自由画线的效果。

查看高德官方文档会发现,并没有可自主画图,文档提供的矢量图功能有:

  • AMap.Polyline 构造折线
  • AMap.BezierCurve 贝塞尔曲线
  • AMap.Circle 构造圆形
  • AMap.Ellipse 构造多边形
  • AMap.Rectangle 构造矩形

除了以上功能,还有根据geojson数据生成矢量图。

但这些并不满足上图效果的场景。那该怎么办?

点动成线

这就是实现自由画线效果的核心思想,线——就是无数个点连接起来的,按照这个思路我们就知道从哪里入手了:

  1. 监听鼠标
  2. 获取点
  3. 将点连接起来
  4. 闭合起止点形成区域

1、监听鼠标事件

// 初始化地图
var map = new AMap.Map("container", {
    center: [116.395577, 39.892257],
    zoom: 14,
  	dragEnable: false, // 禁用拖动
  	defaultCursor: 'crosshair' // 鼠标hover样式
});
// 监听鼠标按下
map.on('mousedown', function(e){
	mouseStatus = 'mousedown'
})
// 监听鼠标移动
map.on('mousemove', function mousemove(e) {
	// 鼠标按下
    if (mouseStatus === 'mousedown') {
    	// 获取鼠标移动生成的点
        drawPath.push(e.lnglat)
    }
})

监听鼠标按下,开始移动,并收集所有的点

2、将点连接起来

// 生成线段
var polyline = new AMap.Polyline({
    path: drawPath,
    strokeWeight: 6, // 线条宽度,默认为 1
    strokeColor: '#ff0000', // 线条颜色
    strokeOpacity: 1,
    lineJoin: 'round', // 折线拐点连接处样式
    bubble: true, // 可冒泡到地图上
});
map.add(polyline);

这里记得需要优化,画线之前需要将之前的线段清除掉,不然每次连线,都是从起始点连接,造成不必要的性能浪费。

3、闭合起止点,形成区域

一般的场景,目的都是得到闭合的区域范围,来获取区域内的数据,所以我们需要将最后鼠标抬起时的点位,和开始点连接起来。并生成矢量图实例,以便使用api得到想要的数据(如:范围坐标、路径坐标等)。

if (drawPath.length) {
    // 绘制成矢量区域实例
    var userDrawPolygon = new AMap.Polygon({
        path: drawPath,
        strokeWeight: 6, // 线条宽度,默认为 1
        strokeColor: '#ff0000', // 线条颜色
        fillOpacity: 0.1,
    });
    map.add(userDrawPolygon);
    drawPath = [] // 清空
    console.log('绘制完成的区域实例对象', userDrawPolygon)
    console.log('绘制区域范围', userDrawPolygon.getBounds())
}

最后附上完成整代码

const drawPath = [] // 所有的点
const mouseStatus = 'mouseup' // 鼠标状态
const startPoint = null // 最开始的点
const endPoint = null // 结束点
const lastPolyLine = null // 最后一段线段
const map = new AMap.Map("container", {
    center: [116.395577, 39.892257],
    zoom: 14,
    dragEnable: false, // 禁用拖动
    defaultCursor: 'crosshair' // 鼠标hover样式
});

map.on('mousedown', mousedown)
map.on('mousemove', mousemove)
map.on('mouseup', mouseup)

// 鼠标按下事件函数
function mousedown(e) {
    mouseStatus = 'mousedown'
}
// 鼠标移动事件函数
function mousemove(e) {
    // 鼠标按下
    if (mouseStatus === 'mousedown') {
        // 记录起始点
        startPoint = startPoint ? startPoint : e.lnglat
        // 存储鼠标移动经过的点
        drawPath.push(e.lnglat)
        // 把之前的渲染过的线段删掉,不然每一次移动生成的线段,都会从头开始渲染
        if (lastPolyLine) {
            map.remove(lastPolyLine)
        }
        // 生成线段
        let polyline = new AMap.Polyline({
            path: drawPath,
            strokeWeight: 6, // 线条宽度,默认为 1
            strokeColor: '#ff0000', // 线条颜色
            strokeOpacity: 1,
            lineJoin: 'round', // 折线拐点连接处样式
            bubble: true, // 可冒泡到地图上
        });
        map.add(polyline);
        // 记录下最后的线段
        lastPolyLine = polyline
    }
}
// 鼠标抬起事件函数
function mouseup(e) {
    // 结束点
    endPoint = e.lnglat
    // 如果结束点未闭合,则自动闭合
    if (endPoint && (endPoint.getLng() !== startPoint.getLng() || endPoint.getLat() !== startPoint.getLat())) {
        drawPath.push(endPoint, startPoint)
    }
    // 删除所有拼接起来的线段
    if (lastPolyLine) {
        map.remove(lastPolyLine)
    }
    if (drawPath.length) {
        // 绘制成矢量区域实例,方便调用api获取所需数据
        let userDrawPolygon = new AMap.Polygon({
            path: drawPath,
            strokeWeight: 6, // 线条宽度,默认为 1
            strokeColor: '#ff0000', // 线条颜色
            fillOpacity: 0.1,
        });
        map.add(userDrawPolygon);
        drawPath = [] // 清空
        console.log('绘制完成的区域实例对象', userDrawPolygon)
        console.log('绘制区域范围', userDrawPolygon.getBounds())
    }
    mouseStatus = 'mouseup' // 恢复默认鼠标状态
    startPoint = null // 最开始的点
    endPoint = null // 结束点
    lastPolyLine = null // 最后一段线段
    // 卸载所有事件
    map.off('mousemove', mousemove);
    map.off('mousedown', mousedown);
    map.off('mouseup', mouseup);
    // 恢复鼠标hover样式
    map.setDefaultCursor('default')
}