高德地图添加自自定义标记点(水波纹)

348 阅读1分钟

效果图

Video_2022-09-21_102841 00_00_00-00_00_30.gif

第一步:安装(这里是在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>