vue3使用leaflet地图

npm i leaflet@1.7.1 axios

下载全国省市区的json数据,可放在public目录下,也可放在后台服务器,有跨域问题,后端解决。

链接: https://pan.baidu.com/s/1LpO17UJgR4dyDO5VZW5hVw?pwd=w2re

页面代码

复制代码
<template>
	<div id="map" style="z-index:1"></div>
</template>
<script lang="ts">
import { reactive, getCurrentInstance, toRefs, onMounted, nextTick, defineComponent, watch } from 'vue';
import "leaflet/dist/leaflet.css";
import * as L from "leaflet";
import axios from "axios";

export default defineComponent({
	setup(props: any, { emit }: any) {
		onMounted(async () => {
			nextTick(() => {
				initMap();
				getmarkers()
			});
		});
		const { proxy } = getCurrentInstance() as any;

		const data = reactive({
			geoJSONlayer: {} as any,
			map: {} as any,
			provinceZoom: 5, // 省级别
			cityZoom: 7, // 市级别
			areaZoom: 9, // 区级别
			townZoom: 11, // 镇级别
			currentZoom: 5, // 当前级别

			markers: [] as any[],
			initCode: "100000", // 初始code
			currentCode: "100000", //当前code
			initName: "全国", //初始name
			currentName: "全国", //当前name
			currentlatlng: [] as any,
			defaultlatlng: [113.88308, 22.55329], // [经度,维度]
			superiorCodeArr: [] as any, //上一级的code
			superiorNameArr: [] as any, //上一级的name
			allBgColor: ["#f7acbc", "#deab8a", "#817936", "#444693", "#ef5b9c", "#fedcbd",],
		});

		// 初始化地图
		const initMap = async () => {
			let mapData = {
				minZoom: 4,
				maxZoom: 18,
				center: [data.defaultlatlng[1], data.defaultlatlng[0]],
				zoom: data.provinceZoom,
				zoomControl: true,
				attributionControl: false,
				crs: L.CRS.EPSG3857,
			}

			let map = L.map("map", mapData);
			var center = map.getCenter(); // 获取新的中心点

			data.map = map; //data上需要挂载
			L.tileLayer(
				"http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}"
			).addTo(map);

			getJson();

			map.on("click", (e: any) => {
			});

			map.on("zoomend", (e: any) => {
				//获取当前放大或者缩小的等级
				data.currentZoom = e.target.getZoom();
				backMapArea(data.currentZoom)
			});
			map.on("moveend", (e: any) => {

			});
		}

		// 显示高亮地图
		const getJson = (val?: any) => {
			let code = val ? val : data.initCode;
			data.currentCode = code
			axios
				.get(`${proxy.VITE_API_REQUEST_URL}/js/mapgeo/${code}.geojson`)
				.then((res) => {
					if (res.status === 200) {
						data.geoJSONlayer = L.geoJSON(res.data, {
							style: () => {
								return {
									color: "white",
									fillColor: data.allBgColor[Math.floor(Math.random() * data.allBgColor.length)],
									weight: 1,
									fillOpacity: 0.5,
								};
							},
							onEachFeature: (feature: any, layer: any) => {
								feature.properties &&
									feature.properties.name &&
									layer.bindTooltip(feature.properties.name, {
										direction: "bottom",
										className: "my_tooltip",
										permanent: true,
									});
							},
						})
							.on("click", (e: any) => {
								let proObj = e.layer.feature.properties;
								console.log("proObj===", proObj);

								if (proObj.childrenNum > 0 && proObj.adcode) {
									data.currentCode = proObj.adcode;
									data.currentName = proObj.name;
									data.superiorNameArr.push(proObj.name)
									let tempAcroutes = [...data.superiorCodeArr, ...proObj.acroutes]
									data.superiorCodeArr = Array.from(new Set(tempAcroutes));
									let zoom =
										data.superiorCodeArr.length === 1
											? data.cityZoom
											: data.superiorCodeArr.length === 2
												? data.areaZoom
												: data.townZoom;
									data.currentZoom = zoom;

									if (proObj.center) { // 根据点击的管辖市区镇的中心经纬度
										data.currentlatlng = proObj.center;
										data.map.flyTo([proObj.center[1], proObj.center[0]], zoom)
									} else { // 根据点击所在点的经纬度
										data.currentlatlng = [e.latlng.lng, e.latlng.lat]
										data.map.flyTo([e.latlng.lat, e.latlng.lng], zoom)
									}

									// 移除数据
									data.geoJSONlayer.remove();
									// 重新加载数据
									getJson(proObj.adcode);
								} else {
									proxy.$message.warning("没有数据");
								}
							})
							.addTo(data.map);
					}
				})
				.catch((err) => {
					// 请求失败时的处理逻辑
					console.log(err);
				});
		}


		// 获取所有的markers
		const getmarkers = () => {
			let list = [
				{ dev_latitude: 22.15329, dev_longitude: 113.12308 },
				{ dev_latitude: 22.25229, dev_longitude: 113.21308 },
				{ dev_latitude: 22.35129, dev_longitude: 113.38138 },
				{ dev_latitude: 22.45429, dev_longitude: 113.48318 },
				{ dev_latitude: 22.55529, dev_longitude: 113.58328 },
				{ dev_latitude: 22.65629, dev_longitude: 113.68358 },
				{ dev_latitude: 24.75729, dev_longitude: 113.78398 },
				{ dev_latitude: 25.75729, dev_longitude: 114.78398 },
				{ dev_latitude: 26.75729, dev_longitude: 115.78398 },
				{ dev_latitude: 27.75729, dev_longitude: 116.78398 },
				{ dev_latitude: 28.75729, dev_longitude: 117.78398 },
			];
			list.map((v) => {
				addmarker(v);
			});
		}
		// 添加marker
		const addmarker = (item: any) => {
			var marker = L.marker([item.dev_latitude, item.dev_longitude]).addTo(data.map);
			marker.bindPopup(`标题`).openPopup();
			data.markers.push(marker);
		}

		const backMapArea = (scale: any) => {
			if (data.superiorCodeArr.length > 1 && scale < data.currentZoom) {
				data.currentCode = data.superiorCodeArr[data.superiorCodeArr.length - 1];
				data.superiorCodeArr.pop();
				data.superiorNameArr.pop();
				data.currentName = data.superiorNameArr.length > 0 ? data.superiorNameArr[data.superiorNameArr.length - 1] : data.initName
				data.geoJSONlayer.remove();
				getJson(data.currentCode)
			} else if (scale <= 5 && data.currentZoom > 5 && data.currentCode != data.initCode) {
				data.currentCode = data.initCode;
				data.superiorCodeArr = [];
				data.superiorNameArr = [];
				data.currentName = data.initName
				data.geoJSONlayer.remove();
				getJson()
			}
		}


		return { ...toRefs(data), }
	}
})
</script>
<style scoped lang="scss">
#map {
	height: 100%;
	width: 100%;
	background-color: #040823;
}

:deep(.my_tooltip) {
	color: #fff;
	background: transparent;
	border: none;
	font-size: 18px;
	box-shadow: none;
}
</style>

效果图

相关推荐
JIngJaneIL27 分钟前
基于java+ vue交友系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·交友
苹果酱056734 分钟前
解决linux mysql命令 bash: mysql: command not found 的方法
java·vue.js·spring boot·mysql·课程设计
拉不动的猪37 分钟前
回顾计算属性的缓存与监听的触发返回结果
前端·javascript·vue.js
小七不懂前端1 小时前
我用 NestJS + Vue3 + Prisma + PostgreSQL 打造了一个企业级 sass 多租户平台
前端·vue.js·后端
进击的野人2 小时前
一个基于 Vue 的 GitHub 用户搜索案例
前端·vue.js·前端框架
+VX:Fegn08952 小时前
计算机毕业设计|基于springboot + vue职位管理推荐系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
前端码农一枚3 小时前
Vue3+TypeScript实现手机扫码功能
vue.js·typescript
钱多多8104 小时前
Vue版本降级操作指南(解决依赖冲突与版本不一致问题)
前端·javascript·vue.js·前端框架
q_19132846954 小时前
基于Springboot+Vue.js的工业人身安全监测系统
vue.js·spring boot·后端·mysql·计算机毕业设计·串口通讯
一念之间lq4 小时前
Elpis 第四阶段· Vue3 完成动态组件建设
前端·vue.js