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";

相关推荐
持续前行1 小时前
vscode 中找settings.json 配置
前端·javascript·vue.js
JosieBook2 小时前
【Vue】11 Vue技术——Vue 中的事件处理详解
前端·javascript·vue.js
安逸点2 小时前
Vue项目中使用xlsx库解析Excel文件
vue.js
一只小阿乐2 小时前
vue 改变查询参数的值
前端·javascript·vue.js·路由·router·网文·未花中文网
小酒星小杜3 小时前
在AI时代下,技术人应该学会构建自己的反Demo地狱系统
前端·vue.js·ai编程
Code知行合壹3 小时前
Pinia入门
vue.js
今天也要晒太阳4733 小时前
element表单和vxe表单联动校验的实现
vue.js
依赖_赖4 小时前
前端实现token无感刷新
前端·javascript·vue.js
hhcccchh5 小时前
学习vue第十三天 Vue3组件深入指南:组件的艺术与科学
javascript·vue.js·学习
zhengxianyi5155 小时前
ruoyi-vue-pro本地环境搭建(超级详细,带异常处理)
前端·vue.js·前后端分离·ruoyi-vue-pro