vue3+leaflet天地图开发

<script setup>
import { onMounted, onUnmounted, ref } from "vue";
// todo 项目使用请放开 leaflet 引入
// import L from 'leaflet';

const emit = defineEmits(["mapLoad"]);

var markers = ref([]);
const mapRef = ref();
const marker = ref();
const map = ref(null);
let current = ref(0);

// 默认多边形
let polygon = ref([]);
// 地图底图
// 第一种
let mapType = ref("vec");
let mapLabelType = ref("cva");
// 第二种
//'img','cia'
let mapType1 = ref(
  L.tileLayer(
    "https://t{s}.tianditu.gov.cn/" +
      "vec" +
      "_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=" +
      "vec" +
      "&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=自己的token",
    {
      subdomains: ["0", "1", "2", "3", "4", "5", "6", "7"],
    }
  )
);
let mapLabelType1 = ref(
  L.tileLayer(
    "https://t{s}.tianditu.gov.cn/" +
      "cva" +
      "_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=" +
      "cva" +
      "&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=自己的token",
    {
      subdomains: ["0", "1", "2", "3", "4", "5", "6", "7"],
    }
  )
);
let mapType2 = ref(
  L.tileLayer(
    "https://t{s}.tianditu.gov.cn/" +
      "img" +
      "_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=" +
      "img" +
      "&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=自己的token",
    {
      subdomains: ["0", "1", "2", "3", "4", "5", "6", "7"],
    }
  )
);
let mapLabelType2 = ref(
  L.tileLayer(
    "https://t{s}.tianditu.gov.cn/" +
      "cia" +
      "_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=" +
      "cia" +
      "&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=自己的token",
    {
      subdomains: ["0", "1", "2", "3", "4", "5", "6", "7"],
    }
  )
);
const initMap = () => {
  map.value.addLayer(mapType1.value);
  map.value.addLayer(mapLabelType1.value);
  map.value.on("click", ({ latlng }) => {
    console.log("坐标:", Object.values(latlng));
  });
  // 回显多边形
  var latlngs = [
    [32.014771671618604, 118.78512382507326],
    [32.01360723504821, 118.815336227417],
    [32.005164627449425, 118.81842613220216],
    [31.992135284867004, 118.81550788879396],
    [31.997885893345625, 118.7985134124756],
  ];
  polygon.value = L.polygon(latlngs, {
    color: "#000eff",
    fillColor: "#0000ed",
    weight: 1,
  });
  map.value.addLayer(polygon.value);
  // 地图初始化完成发送事件
  emit("mapLoad", map.value);
  return map.value;
};
// 绘制数组
let drawList = ref([]);
// 多边形图层
let drawObj = ref(null);
// 多边形对象
let gh = ref(null);
let markerList = ref([]);
let jk = ref(0);
// 绘制
const draw = () => {
  map.value.on("click", ({ latlng }) => {
    console.log("坐标:", Object.values(latlng));
    // 如果已经渲染过多形图,那就重置多边形点位坐标和数组
    if (jk.value == 1) {
      markerList.value.forEach((item) => {
        mapObj.value.removeLayer(item);
      });
      drawList.value = [];
      jk.value = 0;
    }
    // 防止重复绘制,否则会重叠
    if (gh.value) {
      map.value.removeLayer(gh.value);
    }
    if (
      drawList.value.find((item) => {
        return item === Object.values(latlng);
      })
    ) {
    } else {
      // 继续绘制
      drawList.value.push(Object.values(latlng));
      drawObj.value = L.featureGroup(
        drawList.value.map((item) => {
          return L.marker(item);
        })
      );
      // 绘制完成,形成多边形
      gh.value = L.polygon(drawList.value, {
        color: "#000",
        fillColor: "red",
        weight: 2,
      });
      map.value.addLayer(gh.value);
      marker.value = L.marker(latlng).addTo(mapObj.value);
      markerList.value.push(marker.value);
      drawObj.value.on("click", (e) => {
        console.log("批量创建的 marker 触发点击事件", e, "111111");
      });
    }
  });
};
// 删除
const delAll = () => {
  if (gh.value) {
    mapObj.value.removeLayer(gh.value);
    if (markerList.value.length) {
      // 删除多边形点位坐标
      markerList.value.forEach((item) => {
        mapObj.value.removeLayer(item);
      });
    }
  }
  map.value.off("click");
  jk.value = 1;
};
// 完成
const accomplish = () => {
  console.log(drawList.value);
  console.log(markerList.value);
  if (markerList.value.length) {
    markerList.value.forEach((item) => {
      mapObj.value.removeLayer(item);
    });
  }
  console.log(map.value);
  map.value.off("click");
  jk.value = 1;
};

const mapObj = ref();
const markerLayerGroup = ref();
// 清除图层组图层
const clearMarkerLayerGroup = () => {
  if (markerLayerGroup.value) {
    mapObj.value.removeLayer(markerLayerGroup.value);
    markerLayerGroup.value = null;
  }
};
// 创建多个 marker
const createMarkers = () => {
  // 加载前先清除
  clearMarkerLayerGroup();
  const points = [
    [32.0148855, 118.8276675],
    [32.0138855, 118.8477675],
    [31.99239761297989, 118.83490562438966],
  ];

  const markers = points.map((item, index) => {
    // 下面可以设置图标信息
    var markerOptions = {
      // icon:'',
      message: "这是测试信息" + index,
    };
    return L.marker(item, markerOptions);
  });

  // // 将 marker 加载到图层组
  markerLayerGroup.value = L.featureGroup(markers);

  // 绑定事件
  markerLayerGroup.value.on("click", (e) => {
    console.log("批量创建的 marker 触发点击事件", e);
    // 拿到自定义信息   e.layer.options.message
  });

  // 将图层组加载到地图
  markerLayerGroup.value.addTo(mapObj.value);
};
// 在 onMounted 中初始化地图
onMounted(() => {
  map.value = L.map(mapRef.value, {
    center: [29.63184912891887, 91.11785888671876],
    zoom: 5,
    minZoom: 3,
    maxZoom: 22,
    noWrap: true,
    // dragging: false,
    zoomControl: true,
    attributionControl: false,
  });
  mapObj.value = initMap();
  createMarkers();
});

const removeMap = () => {
  if (mapObj.value) {
    mapObj.value.remove();
  }
};
const change = () => {
  // console.log(mapObj.value);
  // console.log(map.value);
  console.log("切换地图");
  if (current.value % 2 === 0) {
    map.value.removeLayer(mapType1.value);
    map.value.removeLayer(mapLabelType1.value);
    map.value.addLayer(mapType2.value);
    map.value.addLayer(mapLabelType2.value);
  } else {
    map.value.removeLayer(mapType2.value);
    map.value.removeLayer(mapLabelType2.value);
    map.value.addLayer(mapType1.value);
    map.value.addLayer(mapLabelType1.value);
  }
  current.value++;
};
// 在组件卸载时删除地图
onUnmounted(() => {
  removeMap();
});
</script>

<template>
  <button @click="change">切换地图底图</button>
  <button @click="draw">开始绘制多边形</button>
  <button @click="accomplish">完成绘制多边形</button>
  <button @click="delAll">删除多边形</button>
  <div ref="mapRef" class="map" @click="didi"></div>
</template>

<style scoped lang="scss">
.map {
  height: 100vh;
  z-index: 0;
}
::v-deep {
  .leaflet-right {
    display: none !important;
  }
}
</style>

安装leaflet

npm install leaflet

在main.js中引入

import "leaflet/dist/leaflet.css";
// 引入Leaflet对象 挂载到Vue上,便于全局使用,也可以单独页面中单独引用
import * as L from "leaflet";

相关推荐
程序媛小果11 分钟前
基于java+SpringBoot+Vue的桂林旅游景点导游平台设计与实现
java·vue.js·spring boot
方才coding1 小时前
1小时构建Vue3知识体系之vue的生命周期函数
前端·javascript·vue.js
man20171 小时前
【2024最新】基于springboot+vue的闲一品交易平台lw+ppt
vue.js·spring boot·后端
阿征学IT1 小时前
vue过滤器初步使用
前端·javascript·vue.js
王哲晓1 小时前
第四十五章 Vue之Vuex模块化创建(module)
前端·javascript·vue.js
发现你走远了1 小时前
『VUE』25. 组件事件与v-model(详细图文注释)
前端·javascript·vue.js
前端小超超2 小时前
vue3 ts项目结合vant4 复选框+气泡弹框实现一个类似Select样式的下拉选择功能
前端·javascript·vue.js
大叔是90后大叔2 小时前
vue3中查找字典列表中某个元素的值
前端·javascript·vue.js
幸运小圣2 小时前
Vue3 -- 项目配置之prettier【企业级项目配置保姆级教程2】
前端·vue.js·vue
ZJ_.2 小时前
Electron 沙盒模式与预加载脚本:保障桌面应用安全的关键机制
开发语言·前端·javascript·vue.js·安全·electron·node.js