vue+leaflet示例:聚合图功能(附源码下载)

demo源码运行环境以及配置

  • 运行环境:依赖Node安装环境,demo本地Node版本:14.19.1。
  • 运行工具:vscode或者其他工具。
  • 配置方式:下载demo源码,vscode打开,然后顺序执行以下命令:
    (1)下载demo环境依赖包命令:npm i
    (2)启动demo命令:npm run dev
    (3)打包demo命令: npm run build:release

示例效果


本篇实现的思路:参考leaflet官网聚合效果插件Leaflet.markercluster:https://github.com/Leaflet/Leaflet.markercluster
这个聚合插件具体使用看github地址,那里有详细说明以及例子。

  • 核心源码
<template>
  <div id="map" ref="mapDiv"></div>
  <div class="titleContainer center">
    <span>vue+leaflet示例:聚合图功能</span>
  </div>
</template>

<script setup>
import { onMounted, reactive, ref } from "vue";
import L from "leaflet";
import "leaflet.markercluster/dist/MarkerCluster.css";
import "leaflet.markercluster/dist/MarkerCluster.Default.css";
import "leaflet.markercluster";
import hgxPic from "@/assets/projectPoint_HGX.png";
import jsztPic from "@/assets/projectPoint_JSZT.png";
import xmxzPic from "@/assets/projectPoint_XMXZ.png";
import xmzsPic from "@/assets/projectPoint_XMZS.png";
// import config from "../config";
// import { useRouter } from "vue-router";
// const router = useRouter();
// const mapDiv = ref(null);
let map = null;
const geojson = {
  type: "FeatureCollection",
  features: [
    {
      type: "Feature",
      geometry: {
        type: "Point",
        coordinates: [113.16305738210656, 23.13667404697526],
      },
      properties: { Name_CHN: "赤岗塔", StationNum: 1, Status: 1 },
    },
    {
      type: "Feature",
      geometry: {
        type: "Point",
        coordinates: [113.10861400100009, 22.993978000000084],
      },
      properties: { Name_CHN: "魁奇路", StationNum: 14, Status: 2 },
    },
    ……
    ……
  ],
};
onMounted(() => {
  initMap();
});
const initMap = () => {
  // 创建地图对象
  map = L.map("map", {
    attributionControl: false,
  }).setView(L.latLng(22.95186415, 113.90271877), 9);
  //创建底图切换数据源
  const baseLayer = L.tileLayer(
    "http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}",
    { crossOrigin: true }
  );
  map.addLayer(baseLayer); //地图默认加载的底图
  //聚合图
  const projectPointLayer = L.markerClusterGroup({
    showCoverageOnHover: false,
    zoomToBoundsOnClick: true,
    chunkedLoading: true,
    maxClusterRadius: 40, //默认80
  }).addTo(map);
  if (geojson) {
    addProjectClusterLayers(geojson, projectPointLayer);
    projectPointLayer.on("click", function (e) {
      e.layer.unbindPopup();
      const elements = getProjectPopupContent(e.layer.options.properties);
      e.layer.bindPopup(elements).openPopup(e.latlng);
    });
  }
};
/*
 * 点单击内容函数
 */
const getProjectPopupContent =  (item) => {
  // 内容及单击事件
  const elements = `<div>
        ${toPopupItemStr("名称", item.Name_CHN)}
        ${toPopupItemStr("站口个数", item.StationNum)}
      </div>`;
  return elements;
};
const toPopupItemStr = (name, value) => {
  return value ? `<b>${name}:</b>${value}<br>` : "";
};
/*
 * 加载聚合图层
 */
const addProjectClusterLayers = async (geojson, clusterlayer) => {
  let markerList = [];
  if (geojson.features.length > 0) {
    for (let i = 0; i < geojson.features.length; i++) {
      if (geojson.features[i].geometry) {
        const properties = geojson.features[i].properties;
        const coordinate = geojson.features[i].geometry.coordinates;
        //根据Status类型不同加载不同图标
        let img = hgxPic;
        switch (properties.Status) {
          case 1:
            img = hgxPic;
            break;
          case 2:
            img = jsztPic;
            break;
          case 3:
            img = xmxzPic;
            break;
          case 4:
            img = xmzsPic;
            break;
        }
        const myIcon = L.icon({
          iconUrl: img,
          iconSize: [25, 25],
        });
        const marker = L.marker(new L.LatLng(coordinate[1], coordinate[0]), {
          properties: properties,
          icon: myIcon,
        });
        markerList.push(marker);
      }
    }
  }
  clusterlayer.addLayers(markerList);
};
</script>

<style scoped>
#map {
  width: 100vw;
  height: 100vh;
}
.titleContainer {
  position: absolute;
  top: 0;
  background: rgba(0, 0, 0, 0.45);
  height: 50px;
  width: 100vw;
  z-index: 999;
  font-size: 14px;
  color: #fff;
  font-size: 28px;
}
.center {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
</style>

下载源码:GIS之家的学习交流圈

posted @ 2025-03-25 20:44  GIS之家  阅读(36)  评论(0)    收藏  举报