地图瓦片
生成地图瓦片需要底图shp文件。一般国内的shp下载方式属于灰色地带,需要使用百度、高德地图下载器才能爬取到shp数据。但是国外有个OpenStreetMap(OSM)类wiki形式的地图资源库,可以下载到全世界各地的shp地图底图,但是精度不是特别高。精度要求特别高的需要自己找地图数据商定制。
百度瓦片
本人用的是爬取下来的百度瓦片,但是百度瓦片有反爬取措施,如下图:
会添加上经纬线,暂时无有效的解决方法。
如何切片?
- 根据不同层级删减一些要素。如当地图层级为5时,只需要显示面积10000000平方米的水域、湖泊要素。
- 使用QGIS或者ArcGIS将刚刚过滤完毕的shp文件导出为GEOJSON文件
- 上传到linux服务器
- 使用mapbox开源的tippecanoe插件,来进行mbtiles瓦片切片。切片一般要比较久的时间,如本人切一个0-14层级的中国瓦片数据,需要20小时左右。
- 切片完成后,生成了一个mbtiles文件,使用如下node服务器读取mbtiles中的pbf瓦片
const resolve = (path) => require("path").resolve(__dirname, path);
const Koa = require("koa");
const Router = require("@koa/router");
const cors = require("koa2-cors");
const MBTiles = require("@mapbox/mbtiles");
const router = new Router();
let mbtiles = null;
// 自己换下mbtiles的地址
new MBTiles(resolve("/opt/map.mbtiles"), (err, mb) => {
if(err) throw err
mbtiles = mb;
});
function getTile(x, y, z) {
return new Promise((resolve, reject) => {
mbtiles.getTile(z, x, y, (err, data, headers) => {
if (err) {
reject(err);
return;
}
resolve(data);
});
});
}
router.get("/:z/:x/:y.pbf", async (ctx, next) => {
let { x, y, z } = ctx.params;
try {
const data = await getTile(x, y, z);
ctx.body = data;
ctx.set("content-encoding", "gzip"); // 注意响应头
ctx.set("content-type", "application/x-protobuf");
} catch (e) {
throw e
}
return next();
});
const app = new Koa();
app.use(
// 跨域
cors({
origin: function (ctx) {
//设置允许来自指定域名请求
// if (ctx.url === '/tile') {
return "*"; // 允许来自所有域名请求
// }
},
maxAge: 500000000000, //指定本次预检请求的有效期,单位为秒。
credentials: true, //是否允许发送Cookie
allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], //设置所允许的HTTP请求方法'
allowHeaders: ["Content-Type", "Authorization", "Accept"], //设置服务器支持的所有头信息字段
exposeHeaders: ["WWW-Authenticate", "Server-Authorization"], //设置获取其他自定义字段
})
);
app.use(router.routes());
app.listen(8848);
监听8848端口
如何使用地图瓦片?
本人使用mapbox来读取切好的瓦片,在style文件中加上如下的source配置(换上你自己的地址):
sources: {
composite: {
type: "vector",
maxzoom: 14,
minzoom: 0,
tiles: ["http://xxxxxxx/{z}/{x}/{y}.pbf"],
},
},
并写上相应的图层样式配置,应该就可以看到屏幕上渲染出的结果了。