效果图
第一步:安装(这里是在vue3项目中使用)
yarn add @amap/amap-jsapi-loader
第二步页面引入
import AMapLoader from '@amap/amap-jsapi-loader'
初始化地图方法
AMapLoader.load({
key: '1983636df10af8114f19a38296ed43ae',
version: "2.0",// 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [],// 需要使用的的插件列表,如比例尺'AMap.Scale'等
}).then(Amap => {
const map = new Amap.Map('map', {
mapStyle: 'amap://styles/e7c9440baaf971702e6542f852a4d582',
zoom: 8
})
})
自定义水波纹标签及样式
<!-- 标签 -->
<div class="radar">
<div class="ripple"></div>
<div class="ripple"></div>
<div class="ripple"></div>
</div>
<!-- 样式 -->
.radar {
width: 100%;
height: 100%;
border-radius: 50%;
position: absolute;
top: 0;
left: 0;
z-index: 2;
.ripple {
width: 0px;
height: 0px;
border-radius: 50%;
position: absolute;
z-index: 1;
box-shadow: 0px 0px 2px 4px #f00;
border: 1px solid #f00;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
animation: ripple 2s linear infinite;
&:nth-child(1) {
animation-delay: 0.666s;
}
&:nth-child(2) {
animation-delay: 1.322s;
}
}
}
// 动画
@keyframes ripple {
to {
width: 60px;
height: 60px;
opacity: 0;
}
}
完整代码:
<template>
<div id="map"></div>
<button @click="removePoints" class="btn">删除点</button>
<button @click="add" class="btn btn1">添加点</button>
</template>
<script lang="ts" setup>
import AMapLoader from '@amap/amap-jsapi-loader'
import { onMounted, reactive } from 'vue'
const mapInfo = reactive({
map: null,
Amap: null,
points: [],
lines: [
{
city: '东西湖区',
address: '吴家山集装箱中心站',
type: '铁路',
name: '东西湖区',
lng: 114.266168,
lat: 30.717014
},
{
city: '东西湖区',
address: '大花岭物流基地',
type: '公路',
name: '东西湖区',
lng: 114.736449,
lat: 30.543493
},
{
city: '武昌区',
address: '武昌火车站',
type: '水路',
name: '武昌区',
lng: 114.140261,
lat: 30.479275
},
{
city: '东西湖区',
address: '舵落口物流基地',
type: '多式联运',
name: '武昌区',
lng: 113.459561,
lat: 30.343232
}
]
})
function initMap() {
AMapLoader.load({
key: '1983636df10af8114f19a38296ed43ae',
version: "2.0",// 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [],// 需要使用的的插件列表,如比例尺'AMap.Scale'等
}).then(Amap => {
const map = new Amap.Map('map', {
mapStyle: 'amap://styles/e7c9440baaf971702e6542f852a4d582',
zoom: 8
})
mapInfo.map = map;
mapInfo.Amap = Amap;
addPoint(mapInfo.lines);
})
}
// 添加点标记
function addPoint (datas: any[]) {
const map: any = mapInfo.map;
const Amap: any = mapInfo.Amap;
const points: any = [];
datas.forEach(v => {
const html = `<div class="radar">
<div class="ripple"></div>
<div class="ripple"></div>
<div class="ripple"></div>
</div>`;
const vNode: any = document.createElement('div')
vNode.className = 'radar-box'
vNode.innerHTML = html;
const doms = vNode.childNodes[0].children
let cirs: any = Array.from(doms)
switch(v. type){
case '铁路':
cirs.forEach((v: any) => {
v.style.boxShadow = '0px 0px 2px 4px #D7CE56';
v.style.border = '1px solid #D7CE56';
})
break
case '公路':
cirs.forEach((v: any) => {
v.style.boxShadow = '0px 0px 2px 4px #1bd928';
v.style.border = '1px solid #1bd928';
})
break
default:
cirs.forEach((v: any) => {
v.style.boxShadow = '0px 0px 2px 4px #f00'
v.style.border = '1px solid #f00'
})
break
}
const marker = new Amap.Marker({
// icon: "https://webapi.amap.com/theme/v1.3/markers/n/mark_r.png",
content: vNode,
position: [v.lng, v.lat],
offset: new AMap.Pixel(-13, -30)
})
map.add(marker)
points.push(marker)
mapInfo.points = points
// 添加信息窗体
const h = `<div class='info_box'>${v.name}</div>`
const infoWindow = new Amap.InfoWindow({
isCustom: true, //使用自定义窗体
content: h,
position: [v.lng, v.lat],
offset: new AMap.Pixel(16, -45)
})
// marker.on('click', () => {
// infoWindow.open(map)
// })
marker.on('mouseover', () => {
infoWindow.open(map)
})
marker.on('mouseout', () => {
map.clearInfoWindow();
})
})
}
function add () {
// 先移除
removePoints()
addPoint(mapInfo.lines)
}
function removePoints() {
const map: any = mapInfo.map
map.remove(mapInfo.points)
}
onMounted(() => {
initMap()
})
</script>
<style lang="scss" scoped>
#map {
width: 100%;
height: 100%;
// 解决标记点被切断的问题
::v-deep(.amap-icon) {
overflow: inherit!important;
}
::v-deep(.radar) {
width: 100%;
height: 100%;
border-radius: 50%;
position: absolute;
top: 0;
left: 0;
z-index: 2;
.ripple {
width: 0px;
height: 0px;
border-radius: 50%;
position: absolute;
z-index: 1;
box-shadow: 0px 0px 2px 4px #f00;
border: 1px solid #f00;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
animation: ripple 2s linear infinite;
&:nth-child(1) {
animation-delay: 0.666s;
}
&:nth-child(2) {
animation-delay: 1.322s;
}
}
}
::v-deep(.info_box) {
background-color: rgba(0, 0, 0, 0.5);
padding: 10px 20px;
border-radius: 5px;
color: #fff;
}
}
@keyframes ripple {
to {
width: 60px;
height: 60px;
opacity: 0;
}
}
.btn {
position: absolute;
top: 15px;
left: 15px;
z-index: 5;
}
.btn1 {
left: 120px;
}
</style>