今天分享一下,使用高德地图api实现上图可自由画线的效果。
查看高德官方文档会发现,并没有可自主画图,文档提供的矢量图功能有:
- AMap.Polyline 构造折线
- AMap.BezierCurve 贝塞尔曲线
- AMap.Circle 构造圆形
- AMap.Ellipse 构造多边形
- AMap.Rectangle 构造矩形
除了以上功能,还有根据geojson数据生成矢量图。
但这些并不满足上图效果的场景。那该怎么办?
点动成线
这就是实现自由画线效果的核心思想,线——就是无数个点连接起来的
,按照这个思路我们就知道从哪里入手了:
- 监听鼠标
- 获取点
- 将点连接起来
- 闭合起止点形成区域
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')
}