Vue3中使用高德地图实现多点生成轨迹

现在需要在高德地图中实现下面功能:在地图上点击后,在点击的位置出现一个标记,第二次以及之后的点击,出现标记,并且当前的标记和上一次的标记出现一条线将他们连接起来,点击鼠标右键,清除所有的点和线。

准备

要在个人网页中使用高德地图,首先要在高德开放平台上创建应用并申请一个key:

得到安全密钥后,在用到地图的组件的js中加入下面代码:

1
2
3
window._AMapSecurityConfig = {
securityJsCode: '安全密钥'
}

安装高德地图SDK:

1
npm install @amap/amap-jsapi-loader

初始化

在模板中创建一个id​为map​的div​:

1
2
3
<template>
<div id="map" />
</template>

并创建initMap​函数初始化地图,其中在AMapLoader.load​函数中,plugins​参数是一个数组,指的是地图中用到的高德地图组件,可以使用的组件在高德地图JSAPI文档中可以查到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import AMapLoader from "@amap/amap-jsapi-loader";

var map = null;
var initMap = function () {
AMapLoader.load({
"key": "***********************",
"version": "2.0",
"plugins": ["AMap.Marker", "AMap.LngLat", "AMap.Polyline"],
}).then((AMap) => {
map = new AMap.Map('map', {
viewMode: "3D",
zoom: 13,
resizeEnable: true
});
})
}
onMounted(initMap);

添加点和直线

添加点是通过鼠标点击来添加的,那就要为地图添加点击事件,高德地图的事件和DOM的事件有些许不同,可以被注册的事件在文档中查到:

1
2
3
map.on('click', function (e) {
console.log(e);
});

打印出来的事件对象,包含了一个AMap.LngLat​,表示的是点击的点的经纬度:

获取到点击到的点的经纬度了,就可以创建一个AMap.Marker对象,并在map上添加上去,为了储存创建的点,还需要创建一个markers数组,并把新创建的点push进去:

1
2
3
4
5
6
7
8
9
var markers = [];

var marker = new AMap.Marker({
map: map,
draggable: true,
position: new AMap.LngLat(e.lnglat.lng, e.lnglat.lat)
});
map.add(marker);
markers.push(marker);

markers数组里有两个或以上marker时,就可以创建AMap.Polyline对象了,线的两点的位置为当前的点和上一次点击的点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if (markers.length >= 2) {
var line = new AMap.Polyline({
strokeColor: '#3366ff',
strokeWeight: 6,
isOutline: true,
outlineColor: 'white'
});
line.setMap(map);
var p1 = markers[markers.length - 1].getPosition();
var p2 = markers[markers.length - 2].getPosition();
var path = [p1, p2];
line.setPath(path);
lines.push(line);
}

现在已经实现了增加点和线了,效果如下:

清除点和线

需要点击右键清除地图上的点和线,同理给地图添加右键点击事件,并在事件中清除markerslines数组中储存的点和线即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
map.on("rightclick", function () {
if (markers.length < 2) {
return;
}
markers.forEach(v => {
v.setMap(null);
})
lines.forEach(v => {
v.setMap(null);
})
markers = [];
lines = [];
})

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<template>
<div id="map" />
</template>

<script setup>
import AMapLoader from '@amap/amap-jsapi-loader';
import { onMounted } from 'vue';

var map = null;
var markers = [];
var lines = [];

window._AMapSecurityConfig = {
securityJsCode: '********'
};

var initMap = function () {
AMapLoader.load({
key: '*******',
version: '2.0',
plugins: ['AMap.Marker', 'AMap.LngLat', 'AMap.Polyline']
}).then((AMap) => {
map = new AMap.Map('map', {
viewMode: '3D',
zoom: 13,
resizeEnable: true
});
map.on('click', function (e) {
var marker = new AMap.Marker({
map: map,
draggable: true,
position: new AMap.LngLat(e.lnglat.lng, e.lnglat.lat)
});
map.add(marker);
markers.push(marker);
if (markers.length >= 2) {
var line = new AMap.Polyline({
strokeColor: '#3366ff',
strokeWeight: 6,
isOutline: true,
outlineColor: 'white'
});
line.setMap(map);
var p1 = markers[markers.length - 1].getPosition();
var p2 = markers[markers.length - 2].getPosition();
var path = [p1, p2];
line.setPath(path);
lines.push(line);
}
});
map.on('rightclick', function () {
if (markers.length < 2) {
return;
}
markers.forEach((v) => {
v.setMap(null);
});
lines.forEach((v) => {
v.setMap(null);
});
markers = [];
lines = [];
});
});
};

onMounted(initMap);
</script>

<style lang="less" scoped>
#map {
overflow: hidden;
width: 100%;
height: 400px;
margin: 0;
font-family: '微软雅黑';
}

.amap-logo {
display: none !important;
}

.amap-copyright {
display: none !important;
}
</style>