《webgis之制作地图切片方法(一) —— QGIS》
《webgis之制作地图切片方法(二) —— gdal2tiles.py》
前言
本文介绍Mapbox开源的一个非常强大的矢量切片工具应用 —— tippecanoe。通过该工具可以将geojson格式的数据切片成 xyz 形式的矢量切片 或者 mbtiles 格式的矢量切片。本文将介绍该工具简单应用方式,并通过 MapboxGL 预览切片。
$ brew install tippecanoe
更多配置项参考官网。
配置项 | 含义 |
---|---|
-zg | 自动选择最大的maxZoom,平衡性能 |
-o | 输出文件 |
custome.json | 切片的文件,仅支持geojson,根据实际情况写 |
tippecanoe -zg -o custom.bmtiles custom.json
配置项 | 含义 |
---|---|
-z | maxZoom,最大的切片层级 |
-Z | minZoom,最小的切片层级 |
-pC | 不压缩文件(gzip) |
-e | 输出文件夹 |
custome.json | 切片的文件,仅支持geojson,根据实际情况写 |
tippecanoe -z10 -Z0 -pC -e xyz custom.json
未压缩的切片放在服务器中以静态文件服务的形式发布,可以使用MapboxGL直接调用。
<html>
<head>
<title>Mapbox Demotitle>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<link href="https://api.mapbox.com/mapbox-gl-js/v2.13.0/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v2.13.0/mapbox-gl.js">script>
head>
<body>
<div id="map" style="width: 100vw; height: 100vh">div>
body>
<script type="text/javascript">
// Get a mapbox API access token
mapboxgl.accessToken = 'token';
// Initialize mapbox map
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/dark-v11',
center: [22.324219, 42.423322],
zoom: 4,
});
map.on('load', () => {
map.addSource('myvct', {
type: 'vector',
tiles: ['http://localhost:3000/geoserver/{z}/{x}/{y}.pbf']
})
map.addLayer({
id: 'mylayer',
source: 'myvct',
"source-layer": 'custom',
type: 'fill',
paint: {
"fill-color": '#0080ff',
'fill-opacity': 0.5
}
})
});
script>
html>
tippecanoe -z10 -Z0 -e xyz custom.json
message : "Unimplemented type: 3"
,这个问题官方也有提到 issues,由此官网也对这个做了补充描述。Content-Encoding: gzip
就可以了。实现目的的方式多种多样,本实验使用 express 实现地图服务支持。服务端关键代码如下:const express = require("express");
const fs = require("fs");
const path = require("path");
const app = express();
const port = 3000;
// 自定义跨域中间件
const allowCors = function (req, res, next) {
res.header("Access-Control-Allow-Origin", req.headers.origin);
res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS");
res.header("Access-Control-Allow-Headers", "Content-Type");
res.header("Access-Control-Allow-Credentials", "true");
next();
};
app.use(allowCors); //使用跨域中间件
// pbf 矢量切片请求接口
app.get("/geoserver/:z/:x/:y", (req, res) => {
const { z, x, y } = req.params;
// 读取pbf文件
const pbfFilePath = `./zipxyz/${z}/${x}/${y}`
if(fs.existsSync(pbfFilePath)){
const file = fs.createReadStream(pbfFilePath);
// 根据pbf文件是否压缩设置相应头
res.setHeader("Content-Encoding", "gzip");
/**
* some program block.
*/
file.pipe(res);
}
});
app.listen(port, () => {
console.log(`server on ${port}`);
});