Skip to content

散点涟漪效果

上次更新 2025年8月20日星期三 3:16:20 字数 0 字 时长 0 分钟

示例

TIP

通过自定义 DivIcon 和 CSS 动画实现标记点的涟漪扩散效果。

新标签页预览

代码实现

vue
<template>
  <div id="map" class="w-full h-96"></div>
</template>

<script setup>
import L from "leaflet";
import "leaflet/dist/leaflet.css";
import { onMounted, ref } from "vue";

const map = ref(null);

onMounted(() => {
  // 初始化地图
  map.value = L.map("map", {
    zoomControl: false,
    attributionControl: false,
    center: [39.9042, 116.4074],
    zoom: 12,
  });

  // 添加底图
  L.tileLayer(
    "http://t{s}.tianditu.gov.cn/vec_w/wmts?layer=vec&style=default&tilematrixset=w&Service=WMTS&Request=GetTile&Version=1.0.0&Format=tiles&TileMatrix={z}&TileCol={x}&TileRow={y}&tk=d32c6748c80f81a44acd8633cea41dfd",
    {
      subdomains: ["0", "1", "2", "3", "4", "5", "6", "7"],
      attribution: "&copy; 天地图",
    }
  ).addTo(map.value);

  // 自定义涟漪图标
  const RippleIcon = L.DivIcon.extend({
    options: {
      className: "ripple-marker",
      iconSize: [20, 20],
    },
  });

  // 创建多个带涟漪效果的标记点
  const points = [
    [39.9042, 116.4074],
    [39.9142, 116.4174],
    [39.8942, 116.3974],
  ];

  points.forEach((point) => {
    L.marker(point, {
      icon: new RippleIcon(),
    }).addTo(map.value);
  });
});
</script>

<style scoped>
.ripple-marker {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(33, 150, 243, 0.8);
  position: relative;
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.3), 0 0 10px rgba(33, 150, 243, 0.5);
}

.ripple-marker::before,
.ripple-marker::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: rgba(33, 150, 243, 0.6);
  transform: translate(-50%, -50%);
}

.ripple-marker::before {
  animation: ripple 2s infinite ease-out;
}

.ripple-marker::after {
  animation: ripple 2s infinite ease-out 0.5s;
}

@keyframes ripple {
  0% {
    transform: translate(-50%, -50%) scale(1);
    opacity: 0.8;
  }
  50% {
    opacity: 0.4;
  }
  100% {
    transform: translate(-50%, -50%) scale(3.5);
    opacity: 0;
  }
}
</style>
关注公众号