Vue+Mapboxgl 试手(待更新)

手动狗头,换选型就是这么突然。
选用框架:Vue3+Vite+Mapboxgl

在工程中引入mapboxgl

使用了好心人给的 mapboxgl.js 和 mapboxgl.css,放在 public/mapboxgl 目录下,在 index.html 中引入,mapboxgl可作为全局变量使用:

<!DOCTYPE html>
<html lang="en">
  <link>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>mapbox</title>
    <link rel="stylesheet" href="./mapboxgl/mapbox-gl.css" />
    <script src="./mapboxgl/mapbox-gl.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

初始化地图及加载矢量图层

为方便管理,在components目录下新建 MapContainer.vue 组件,在utils目录下新建 init-map-container.js 方法(把完成初始化的map挂在window下方便全局调用),并在vue组件中调用。
MapContainer.vue

<template>
	<div id="map" :class="[theme + '-theme']"></div>
</template>

<script setup>
import { initMap } from "@/utils/init-map-container.js";
onMounted(() => {
	initMap("map");
});
</script>

<style scoped>
#map {
	width: 100%;
	height: 100%;
}
</style>

init-map-container.js

/* global mapboxgl */
export function initMap(mapId) {
	let imgUrl = "http://t0.tianditu.gov.cn/img_w/wmts?tk=" + tk; // 用的是天地图,换自己的token
	let layerName = "img";
	let map = new mapboxgl.Map({
		container: mapId, // container id 绑定的组件的id
		style: {
			version: 8,
			sources: {
				mapsource: {
					type: "raster",
					tiles: [imgUrl + "&SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=" + layerName + "&STYLE=default&TILEMATRIXSET=w&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=tiles"],
					tileSize: 256,
				},
			}, //分别加载多个天地图的图层
			layers: [
				{
					id: "mapsource",
					type: "raster",
					source: "mapsource",
					minzoom: 0,
					maxzoom: 17,
				},
			],
			center: [117.110805, 36.663046],
			zoom: 3,
			// dragRotate:false
		},
		preserveDrawingBuffer: true,
	});
	window.map = map;

	map.on("load", function () {
		// 在此加载一些其他的基础资源,如图层、图标
	});
}

全局注册地图相关方法

在utils目录下新建map-func.js,管理相关地图方法。因为我懒,所以在main.js中全局定义了$mapFunc。
map-func.js

function getLayer(layerId) {
	return window.map.getLayer(layerId);
}

export default {
	getLayer
};

main.js

import mapFunc from "./utils/map-func.js";
const app = createApp(App);
app.mount("#app");
app.config.globalProperties.$mapFunc = mapFunc;
export default app; // 把vue app导出,这样在单独的js文件中才可以使用mapFunc

在vue文件中使用:

<script setup>
import { getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance();
const demoMethod = () => {
	proxy.$mapFunc.getLayer(id);
};
</script>

在js文件中使用:

// import { getLayer } from "@/utils/map-func.js"; // 全局注册mapFunc后,这样在js中引入是无效的,会报错
import context from "../main.js";
const $mapFunc = context.config.globalProperties.$mapFunc;
const demoMethod = () => {
	$mapFunc.getLayer(id);
};

常用地图方法(待更新)

根据id获取图层对象

/**
 * @description: 通过id获取图层
 * @param {*} layerId
 * @return {*}
 */
function getLayer(layerId) {
	return window.map.getLayer(layerId);
}

根据id获取数据源对象

此处默认数据源都在同名图层后多加一个"-source"

/**
 * @description: 通过id获取数据源
 * @param {*} layerId
 * @return {*}
 */
function getSource(layerId) {
	return window.map.getSource(layerId + "-source");
}

图层显隐

/**
 * @description: 控制图层显隐(使用时,对初次加载图层就定义了visibility为"visible"的图层有效,否则会有bug)
 * @param {*} layerId
 * @param {*} visible
 * @param {*} verify 是否验证图层存在,默认不验证
 * @return {*}
 */
function toggleLayerVisible(layerId, visible, verify = false) {
	if (verify) {
		if (!getLayer(layerId)) return;
	}
	const visibility = window.map.getLayoutProperty(layerId, "visibility");
	if (visible !== undefined) {
		window.map.setLayoutProperty(layerId, "visibility", visible ? "visible" : "none");
		return;
	}
	if (visibility === "visible") {
		window.map.setLayoutProperty(layerId, "visibility", "none");
	} else {
		window.map.setLayoutProperty(layerId, "visibility", "visible");
	}
}
posted @ 2023-03-04 19:27  宇宙野牛  阅读(386)  评论(0编辑  收藏  举报