MapboxGL 客户端的自托管矢量切片呈现不正确
Self hosted Vector Tiles for MapboxGL Client rendered incorrectly
我正在尝试在 Node.js 中设置一个 Web 服务器,该服务器使用 MapboxGL JS 提供要在浏览器中显示的矢量切片。矢量切片的数据存储在 PostGIS 数据库中。
我当前的设置似乎在朝着正确的方向发展,因为我可以看到矢量切片正在加载并显示在浏览器中。但是渲染结果不正确(这是我地图的一部分的屏幕截图):
绿色建筑足迹的上半部分在图像的下半部分重复出现。放大和缩小时,我还注意到建筑物 "changing" 的位置,这表明瓷砖以某种方式呈现偏移或不正确的范围......导入的数据位于 SRID 4326 中。
这是我的代码:
var zlib = require('zlib');
var express = require('express');
var mapnik = require('mapnik');
var Promise = require('promise');
var SphericalMercator = require('sphericalmercator');
var mercator = new SphericalMercator({
size: 256 //tile size
});
mapnik.register_default_input_plugins();
var app = express();
app.get('/vector-tiles/:layerName/:z/:x/:y.pbf', function(req, res) {
var options = {
x: parseInt(req.params.x),
y: parseInt(req.params.y),
z: parseInt(req.params.z),
layerName: req.params.layerName
};
makeVectorTile(options).then(function(vectorTile) {
zlib.deflate(vectorTile, function(err, data) {
if (err) return res.status(500).send(err.message);
res.setHeader('Content-Encoding', 'deflate');
res.setHeader('Content-Type', 'application/x-protobuf');
res.send(data);
});
});
});
function makeVectorTile(options) {
var extent = mercator.bbox(options.x, options.y, options.z, false, '4326');
var map = new mapnik.Map(256, 256);
map.extent = extent;
var layer = new mapnik.Layer(options.layerName);
layer.datasource = new mapnik.Datasource({
type: 'postgis',
dbname: 'databasename',
table: options.layerName,
user: 'username',
password: 'password'
});
layer.styles = ['default'];
map.add_layer(layer);
return new Promise(function (resolve, reject) {
var vtile = new mapnik.VectorTile(parseInt(options.z), parseInt(options.x), parseInt(options.y));
map.render(vtile, function (err, vtile) {
if (err) return reject(err);
resolve(vtile.getData());
});
});
}
自定义矢量数据源包含在地图中是这样的:
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v8',
zoom: 10,
center: [13.739910, 51.051151]
});
map.on('style.load', function () {
map.addSource('local', {
type: 'vector',
tiles: ["http://localhost:3333/vector-tiles/building/{z}/{x}/{y}.pbf"]
});
map.addLayer({
"id": "park",
"source": "local",
"type": "fill",
"source-layer": "building",
"paint": {
"fill-color": "#5DC73A"
}
});
});
以上示例代码中的地图使用了不正确的空间参考系统。矢量瓦片使用 Web Mercator Projection,但 mapnik 地图是在 WGS84 中初始化的。当向 mercator.bbox
方法和 mapnik.Map
构造函数显式提供 Web 墨卡托时,矢量切片在客户端中正确呈现:
var extent = mercator.bbox(options.x, options.y, options.z, false, '3857');
var map = new mapnik.Map(256, 256, '+init=epsg:3857');
我正在尝试在 Node.js 中设置一个 Web 服务器,该服务器使用 MapboxGL JS 提供要在浏览器中显示的矢量切片。矢量切片的数据存储在 PostGIS 数据库中。
我当前的设置似乎在朝着正确的方向发展,因为我可以看到矢量切片正在加载并显示在浏览器中。但是渲染结果不正确(这是我地图的一部分的屏幕截图):
绿色建筑足迹的上半部分在图像的下半部分重复出现。放大和缩小时,我还注意到建筑物 "changing" 的位置,这表明瓷砖以某种方式呈现偏移或不正确的范围......导入的数据位于 SRID 4326 中。
这是我的代码:
var zlib = require('zlib');
var express = require('express');
var mapnik = require('mapnik');
var Promise = require('promise');
var SphericalMercator = require('sphericalmercator');
var mercator = new SphericalMercator({
size: 256 //tile size
});
mapnik.register_default_input_plugins();
var app = express();
app.get('/vector-tiles/:layerName/:z/:x/:y.pbf', function(req, res) {
var options = {
x: parseInt(req.params.x),
y: parseInt(req.params.y),
z: parseInt(req.params.z),
layerName: req.params.layerName
};
makeVectorTile(options).then(function(vectorTile) {
zlib.deflate(vectorTile, function(err, data) {
if (err) return res.status(500).send(err.message);
res.setHeader('Content-Encoding', 'deflate');
res.setHeader('Content-Type', 'application/x-protobuf');
res.send(data);
});
});
});
function makeVectorTile(options) {
var extent = mercator.bbox(options.x, options.y, options.z, false, '4326');
var map = new mapnik.Map(256, 256);
map.extent = extent;
var layer = new mapnik.Layer(options.layerName);
layer.datasource = new mapnik.Datasource({
type: 'postgis',
dbname: 'databasename',
table: options.layerName,
user: 'username',
password: 'password'
});
layer.styles = ['default'];
map.add_layer(layer);
return new Promise(function (resolve, reject) {
var vtile = new mapnik.VectorTile(parseInt(options.z), parseInt(options.x), parseInt(options.y));
map.render(vtile, function (err, vtile) {
if (err) return reject(err);
resolve(vtile.getData());
});
});
}
自定义矢量数据源包含在地图中是这样的:
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v8',
zoom: 10,
center: [13.739910, 51.051151]
});
map.on('style.load', function () {
map.addSource('local', {
type: 'vector',
tiles: ["http://localhost:3333/vector-tiles/building/{z}/{x}/{y}.pbf"]
});
map.addLayer({
"id": "park",
"source": "local",
"type": "fill",
"source-layer": "building",
"paint": {
"fill-color": "#5DC73A"
}
});
});
以上示例代码中的地图使用了不正确的空间参考系统。矢量瓦片使用 Web Mercator Projection,但 mapnik 地图是在 WGS84 中初始化的。当向 mercator.bbox
方法和 mapnik.Map
构造函数显式提供 Web 墨卡托时,矢量切片在客户端中正确呈现:
var extent = mercator.bbox(options.x, options.y, options.z, false, '3857');
var map = new mapnik.Map(256, 256, '+init=epsg:3857');