一、注册并登录高德地图开放平台,申请密钥
<script src="//webapi.amap.com/maps?v=1.4.15&key=自己申请的密钥&plugin=自己所需要的插件"></script>
二、引入高德地图加载器
npm i @amap/amap-jsapi-loader --save
三、封装一个自定义地图子组件并初始化地图
<template>
<div
ref="map"
class="map-comp"
id="container"
style="width: 1710px;height: 845px;"
></div>
</template>
<script>
import "echarts-extension-amap";
import * as echarts from "echarts";
export default {
name: "MapComp",
data() {
return {
map: null,
chart: null,
};
},
mounted() {
this.initMap();
},
methods: {
createOption() {
return {
amap: {
resizeEnable: true,
mapStyle: "amap://styles/darkblue", //地图颜色样式
viewMode: "3D", //是否启用3d地图
pitch: 30, //视角高度
skyColor: "#021929", //天空颜色
center: [108.94, 34.34] // 中心点坐标
},
};
},
initMap() {
const option = this.createOption();
const chart = (this.chart = echarts.init(
document.getElementById("container")
));
chart.setOption(option);
}
}
};
</script>
<style lang="scss" scoped>
.map-comp {
width: 100%;
height: 100%;
}
</style>
初始化地图的图片 注意上面提到引入自己的key和所需要用到的插件,我们这里用到的高德地图插件(plugin=AMap.CustomLayer&plugin=AMap.DistrictSearch),放入script标签src里面即可。
四、封装定义一个父组件,并将子组件导入
<template>
<map-comp
:points="points"
:to-scatters="toScatters"
/>
</template>
<script>
import MapComp from "./indexSon.vue";
export default {
name: "App",
components: {
MapComp
},
data() {
return {
// 飞线的数据格式
points: [
{
from: [114.298572, 30.584355],
to: [113.665412, 34.757975]
},
{
from: [114.298572, 30.584355],
to: [114.298572, 30.584355]
},
{
from: [114.298572, 30.584355],
to: [116.405285, 39.904989]
}
],
// 点的数据格式
toScatters: [
[113.665412, 34.757975, "郑州市"],
[114.298572, 30.584355, "武汉市"],
[116.405285, 39.904989, "北京市"]
]
};
},
};
</script>
五、子组件使用props接收父组件传过来的数据,并渲染呼吸灯和飞线
export default {
props: {
points: {
type: Array,
default: () => []
},
toScatters: {
type: Array,
default: () => []
},
},
methods:{
createOption() {
return {
animation: true,
series: [
//呼吸灯
{
name: "scatter",
type: "effectScatter",
zlevel: 2,
// 使用高德地图坐标系
coordinateSystem: "amap",
data: this.toScatters, //数据格式[y,x,name]
symbolSize: 20, // 设置点的大小
encode: {
//维度
value: 2
},
label: {
normal: {
formatter: "{@[2]}", //title提示的文字@后为索引
position: "right", //显示位置
show: true
},
emphasis: {
//重点显示
show: true
}
},
itemStyle: {
normal: {
color: "#00c1de" //颜色
}
},
hoverAnimation: true,
tooltip: {
trigger: "item",
formatter: "123"
}
},
//飞线
{
type: "lines",
zlevel: 1,
coordinateSystem: "amap",
animation: false,
effect: {
show: true,
period: 2,
symbol: "pin",
symbolSize: 8,
trailLength: 0.5
},
label: {
normal: {
show: false
}
},
lineStyle: {
normal: {
width: 2, //尾迹线条宽度
opacity: 0, //尾迹线条透明度
curveness: 0.2 //尾迹线条曲直度
}
},
//数据格式
data: this.points.map(item => {
return {
coords: [item.from, item.to]
};
})
}
]
};
},
}
}
六、在每个呼吸灯设置打开弹窗显示一些数据
<script>
export default {
data() {
return {
district: new window.AMap.DistrictSearch({
extensions: "all",
subdistrict: false
}),
polygons: null
};
},
mounted() {
this.initMap();
},
methods: {
initMap() {
this.map = chart
.getModel()
.getComponent("amap")
.getAMap();
// 选中一个再点击另一个让其他的弹出窗关闭
this.map.on("click", () => {
if (this.infoWindow) this.infoWindow.close();
if (this.polygons) {
this.map.remove(this.polygons);
this.polygons = null;
}
});
// 设置点击事件将数据传给createInfoWindow方法
chart.on("click", e => {
if (e.componentSubType === "effectScatter" && e.data[3]) {
if (this.infoWindow) this.infoWindow.close();
this.infoWindow = this.createInfoWindow(e.data[3]);
this.infoWindow.open(this.map, e.data);
}
});
},
// 设置窗体信息和样式
createInfoWindow(info) {
return new window.AMap.InfoWindow({
anchor: "top-center",
isCustom: true,
offset: new window.AMap.Pixel(0, 15),
content: `<div class="custom-info-window top-center">
<div>当前位置信息</div>
<div>提交时间:${info.time}</div>
<div>队伍名称:${info.name}</div>
<div>漏洞单位名称:${info.bugCompanyName}</div>
<div>漏洞类型:${info.bugType}</div>
<div>安全评级:${info.bugLevel}</div>
<div class="amap-info-sharp"></div>
</div>`
});
}
}
};
</script>
<style lang="scss" scoped>
.map-comp {
width: 100%;
height: 100%;
}
</style>
<style>
.custom-info-window {
color: #fff;
background: rgba(25, 93, 202, 0.5);
font-size: 12px;
border: 1px solid rgba(25, 93, 202, 0.5);
}
.custom-info-window div:not(.amap-info-sharp) {
padding: 2px 10px;
}
.custom-info-window div:first-of-type {
border-bottom: 1px solid rgba(25, 93, 202, 0.5);
text-align: center;
}
.top-center .amap-info-sharp {
border-bottom-color: rgba(25, 93, 202, 0.5);
}
</style>
七、子组件的完整代码
<template>
<div
ref="map"
class="map-comp"
id="container"
style="width: 1710px;height: 845px;"
></div>
</template>
<script>
import "echarts-extension-amap";
import * as echarts from "echarts";
export default {
name: "MapComp",
props: {
points: {
type: Array,
default: () => []
},
toScatters: {
type: Array,
default: () => []
},
},
data() {
return {
map: null,
chart: null,
district: new window.AMap.DistrictSearch({
extensions: "all",
subdistrict: false
}),
polygons: null
};
},
mounted() {
this.initMap();
},
methods: {
createOption() {
return {
amap: {
resizeEnable: true,
mapStyle: "amap://styles/darkblue",
viewMode: "3D", //是否启用3d地图
pitch: 30, //视角高度
skyColor: "#021929",
showLabel: false, // 是否显示城市的名称
center: [108.94, 34.34] // 中心点坐标
},
animation: true,
series: [
//呼吸灯
{
name: "scatter",
type: "effectScatter",
zlevel: 2,
// 使用高德地图坐标系
coordinateSystem: "amap",
data: this.toScatters, //数据格式[y,x,name]
symbolSize: 20, // 设置呼吸灯的大小
encode: {
//维度
value: 2
},
label: {
normal: {
formatter: "{@[2]}", //title提示的文字@后为索引
position: "right", //显示位置
show: true
},
emphasis: {
//重点显示
show: true
}
},
itemStyle: {
normal: {
color: "#00c1de" //颜色
}
},
hoverAnimation: true,
tooltip: {
trigger: "item",
formatter: "123"
}
},
//飞线
{
type: "lines",
zlevel: 1,
coordinateSystem: "amap",
animation: false,
effect: {
show: true,
// constantSpeed: 60,
period: 2,
symbol: "pin",
symbolSize: 8,
trailLength: 0.5
},
label: {
normal: {
show: false
}
},
lineStyle: {
normal: {
width: 2, //尾迹线条宽度
opacity: 0, //尾迹线条透明度
curveness: 0.2 //尾迹线条曲直度
}
},
//数据格式
data: this.points.map(item => {
return {
coords: [item.from, item.to]
};
})
}
]
};
},
initMap() {
const option = this.createOption();
const chart = (this.chart = echarts.init(
document.getElementById("container")
));
chart.setOption(option);
// get amap instance
this.map = chart
.getModel()
.getComponent("amap")
.getAMap();
this.map.on("click", () => {
if (this.infoWindow) this.infoWindow.close();
if (this.polygons) {
this.map.remove(this.polygons);
this.polygons = null;
}
});
chart.on("click", e => {
if (e.componentSubType === "effectScatter" && e.data[3]) {
if (this.infoWindow) this.infoWindow.close();
this.infoWindow = this.createInfoWindow(e.data[3]);
this.infoWindow.open(this.map, e.data);
}
});
},
createInfoWindow(info) {
return new window.AMap.InfoWindow({
anchor: "top-center",
isCustom: true,
offset: new window.AMap.Pixel(0, 15),
content: `<div class="custom-info-window top-center">
<div>烽火</div>
<div>提交时间:${info.time}</div>
<div>名称:${info.name}</div>
<div class="amap-info-sharp"></div>
</div>`
});
}
}
};
</script>
<style lang="scss" scoped>
.map-comp {
width: 100%;
height: 100%;
}
</style>
<style>
.custom-info-window {
color: #fff;
background: rgba(25, 93, 202, 0.5);
font-size: 12px;
border: 1px solid rgba(25, 93, 202, 0.5);
}
.custom-info-window div:not(.amap-info-sharp) {
padding: 2px 10px;
}
.custom-info-window div:first-of-type {
border-bottom: 1px solid rgba(25, 93, 202, 0.5);
text-align: center;
}
.top-center .amap-info-sharp {
border-bottom-color: rgba(25, 93, 202, 0.5);
}
</style>
八、按照以上步骤操完成之后会得到这样的一个地图,希望能帮到大家