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