目录
- 1.前言
- 2.安装mapbox
- 3.vue3创建map组件
- 4.完善map组件
- 5.mapbox图标和字体本地化
- 6.完整代码
-
- [6.1 vue版本](#6.1 vue版本)
- [6.2 原生js版本](#6.2 原生js版本)
- 7.总结
1.前言
现在我们有这样的一个需求,将mapbox
在本地部署,网上也有不少讲mapbox
本地部署的教程,但是在我看来,很多都没有讲到点上,因为都是在讲字体库和图标库怎么在本地加载。试想一下,如果我要加载的底图不是矢量切片,就不用那些字体库和图标库了,那我为什么还要费那个劲去折腾呢?因此本文我们来梳理一下vue3
环境下mapbox
本地部署。非常灵活,加不加载字体库和图标库,都可自己设置,同样,也不需要token
,更不需要去替换node_modules
里mapbox
的某个文件,因为根本就用不到mapbox
的资源,实现真正的离线部署。
2.安装mapbox
javascript
npm install mapbox-gl
3.vue3创建map组件
在vue3
环境搭建完毕之后,我们只需要新建一个map组件即可。并设置好div容器的样式
javascript
<template>
<div ref="mapContainer" class="map-container"></div>
</template>
<script setup>
</script>
<style scoped>
.map-container {
flex: 1;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
</style>
4.完善map组件
我们现在要初始化map
,但是我不想一初始化就去加载mapbox
默认图层,因此在初始化map
时,把layers
和sources
全部置为空。
javascript
import mapboxgl from 'mapbox-gl'
import 'mapbox-gl/dist/mapbox-gl.css';
let mapContainer = ref();
let map = new mapboxgl.Map({
container: mapContainer.value,
center: [106.741891, 34.054211],
zoom: 3,
style: {
"version": 8,
layers: [],
sources: {},
},
});
OK,现在map
初始化好了。我们要加载我们自己的图层,或者天地图的图层,这里我们就以天地图图层为例。
javascript
map.on('load', function () {
map.addSource('tianDiTu', {
type: 'raster',
tiles: [
'http://t0.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=你的token'
],
tileSize: 256
});
// 添加天地图的 layer
map.addLayer({
id: 'tianDiTu-layer',
type: 'raster',
source: 'tianDiTu'
});
});
看下效果
再看一下NetWork
,全程没有任何请求mapbox
的资源
恭喜,现在你已经实现了mapbox
的本地部署了。关于图层你换成自己的就可以了。但如果你还是想使用mapbox
提供的样式,那么你可以这么设置,接着往下看。
5.mapbox图标和字体本地化
这个其实非常简单,你只需要把mapbox
的字体(glyphs
)和图标(sprite
)下载下来,放在项目中保证可以访问就可以了。如果找不到,可以去这里下载:mapbox资源下载
我将资源放到了项目的static
文件夹下:
我们在浏览器里访问一下,看看能不能访问的到,确保访问OK。
我们在浏览器里访问一下,看看能不能访问的到,确保访问OK。现在重新初始化一下map
javascript
let baseUrl = 'http://localhost:5173/src/static/mapbox1.13.3';
let map = new mapboxgl.Map({
container: mapContainer.value,
center: [106.741891, 34.054211],
zoom: 3,
style: {
"version": 8,
"sprite": baseUrl + "/sprites/sprite",
"glyphs": baseUrl + "/fonts/{fontstack}/{range}.pbf",
layers: [],
sources: {},
},
});
如果你这样配置了还去mapbox
加载资源的话,你可以加一个transformRequest
选项,处理一下访问路径,这种写法是我在官网找到的,目前还没看到有哪个讲离线部署的博文讲到这个函数,作者也算是首创了吧。
javascript
let baseUrl = 'http://localhost:5173/src/static/mapbox1.13.3';
let map = new mapboxgl.Map({
container: mapContainer.value,
center: [106.741891, 34.054211],
zoom: 3,
style: {
"version": 8,
"sprite": baseUrl + "/sprites/sprite",
"glyphs": baseUrl + "/fonts/{fontstack}/{range}.pbf",
layers: [],
sources: {},
},
transformRequest: (url, resourceType) => {
if (resourceType === 'Glyphs') {
url = url.split("?")[0].replace("https://api.mapbox.com/fonts/v1/mapbox", baseUrl + "/fonts")
} else if (resourceType === 'SpriteJSON' || resourceType === 'SpriteImage') {
url = url.split("?")[0].replace("https://api.mapbox.com/styles/v1/mapbox/streets-v12", baseUrl + "/sprites")
}
return { url: url };
}
});
接下来就还是天地图图层的加载,或者矢量切片图层的加载,矢量切片可以使用GeoServer
来切,比较简单,这里就不再赘述了。
6.完整代码
6.1 vue版本
javascript
<template>
<div ref="mapContainer" class="map-container"></div>
</template>
<script setup>
import mapboxgl from 'mapbox-gl'
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
import 'mapbox-gl/dist/mapbox-gl.css';
let mapContainer = ref();
let baseUrl = 'http://localhost:5173/src/static/mapbox1.13.3';
onMounted(() => {
let map = new mapboxgl.Map({
container: mapContainer.value,
center: [106.741891, 34.054211],
zoom: 3,
style: {
"version": 8,
// "sprite": baseUrl + "/sprites/sprite",
// "glyphs": baseUrl + "/fonts/{fontstack}/{range}.pbf",
layers: [],
sources: {},
},
});
map.on('load', function () {
map.addSource('tianDiTu', {
type: 'raster',
tiles: [
'http://t0.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=你的token'
],
tileSize: 256
});
// 添加天地图的 layer
map.addLayer({
id: 'tianDiTu-layer',
type: 'raster',
source: 'tianDiTu'
});
});
});
</script>
<style scoped>
.map-container {
flex: 1;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
</style>
6.2 原生js版本
javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../static/mapbox1.13.3/mapbox-gl.js"></script>
<link rel="stylesheet" href="../static/mapbox1.13.3/mapbox-gl.css" />
<style>
html,
body {
padding: 0;
margin: 0;
height: 100%;
overflow: hidden;
}
#map {
height: 100%;
z-index: 0;
}
</style>
</head>
<body>
<div id='map'></div>
<script>
let url = 'http://localhost:5173/src/static/mapbox1.13.3';
let map = new mapboxgl.Map({
container: 'map',
center: [106.741891, 34.054211],
zoom: 3,
style: {
"version": 8,
"sprite": url+"/sprites/sprite",
"glyphs": url+"/fonts/{fontstack}/{range}.pbf",
"sources": {
"tdt-tiles": {
//矢量类型
'type': 'raster',
'tileSize': 256,
"tiles": [
//天地图
"http://t0.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=你的token",
]
}
},
layers: [{
id: 'layer-tiles',
type: 'raster',
source: 'tdt-tiles'
}]
}
});
</script>
</body>
</html>
7.总结
本文详细的梳理了mapbox
的本地化部署,并且讲解了mapbox
中天地图图层的加载,以及矢量切片图层加载时的资源访问问题,通过transformRequest
函数可以灵活的解决访问资源的问题。最后本文给出了mapbox
离线环境搭建的vue
版本和原生js
版本,希望对读者有所帮助,回见~