Skip to content

自定义地图样式

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

示例

TIP

通过自定义 GeoJSON 样式和交互效果,实现中国省份地图的样式定制。

新标签页预览

代码实现

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: [35.8617, 104.1954],
    zoom: 4,
  });

  // 自定义地图样式
  const customStyle = {
    color: "#3498db",
    weight: 0,
    opacity: 0.8,
    fillColor: "#ecf0f1",
    fillOpacity: 0.6,
    dashArray: null,
  };

  // 添加底图
  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);

  // 加载中国行政区划GeoJSON数据
  fetch("https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=100000_full")
    .then((response) => response.json())
    .then((data) => {
      // 创建GeoJSON图层
      L.geoJSON(data, {
        style: (feature) => ({
          ...customStyle,
          fillColor: getRandomColor(),
        }),
        onEachFeature: (feature, layer) => {
          // 添加省份名称标签
          const center = layer.getBounds().getCenter();
          L.marker(center, {
            icon: L.divIcon({
              className: "province-label",
              html: feature.properties.name,
              iconSize: [100, 40],
              iconAnchor: [50, 20],
            }),
          }).addTo(map.value);

          // 添加鼠标悬停效果
          layer.on({
            mouseover: (e) => {
              const layer = e.target;
              layer.setStyle({
                weight: 0,
                color: "#1890ff",
                fillOpacity: 0.9,
                dashArray: null,
                fillColor: "#e6f7ff",
              });
              layer
                .bindTooltip(feature.properties.name, {
                  className: "custom-tooltip",
                  direction: "auto",
                  permanent: false,
                  sticky: true,
                  opacity: 0.9,
                  offset: [0, -10],
                })
                .openTooltip();
            },
            mouseout: (e) => {
              const layer = e.target;
              layer.setStyle({
                ...customStyle,
                fillColor: layer.options.fillColor,
                weight: 0,
                fillOpacity: 0.6,
              });
              layer.closeTooltip();
            },
          });
        },
      }).addTo(map.value);
    });
});

// 生成随机颜色函数
function getRandomColor() {
  const colors = [
    "#c12e34",
    "#e6b600",
    "#0098d9",
    "#2b821d",
    "#005eaa",
    "#339ca8",
    "#cda819",
    "#32a487",
  ];
  return colors[Math.floor(Math.random() * colors.length)];
}
</script>

<style scoped>
.province-label {
  background: transparent;
  border: none;
  box-shadow: none;
  font-size: 14px;
  font-weight: bold;
  color: #333;
  text-shadow: 2px 2px 3px rgba(255, 255, 255, 0.8);
}
</style>
关注公众号