I am trying to set up a web server in Node.js that serves vector tiles to be displayed in a browser using MapboxGL JS. The data for the vector tiles is stored in a PostGIS database.
this is my database scheme: CREATE TABLE IF NOT EXISTS earthquakes( table_id SERIAL, properties jsonb not null, geom geometry(GeometryZ,4326), primary key (table_id));
earthquakes has properties inside the geojson and I store each feature in database.
For example, earthquakes has this properties: "properties": { "id": "ak16994521", "mag": 2.3, "time": 1507425650893, "felt": null, "tsunami": 0 }
. You can see all geojson here.
My current set up seems to going in the right direction, as I can see vector tiles being loaded and displayed in the browser, and the rendered result is correct.
However, when I click on a feature only return table_id and dont return properties of each feature.
How can send properties???
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('/:namelayer/:z/:x/:y.pbf', (req, res, next) => {
var options = {
x: parseInt(req.params.x),
y: parseInt(req.params.y),
z: parseInt(req.params.z),
layerName: req.params.namelayer
};
makeVectorTile(options).then( (vectorTile) => {
zlib.deflate(vectorTile, (err, data) => {
if (err) return res.status(500).send(err.message);
res.setHeader('Content-Encoding', 'deflate');
res.setHeader('Content-Type', 'application/x-protobuf');
return res.send(data);
});
});
});
function makeVectorTile(options) {
var extent = mercator.bbox(options.x, options.y, options.z, false, '3857');
var map = new mapnik.Map(256, 256, '+init=epsg:3857');
map.extent = extent;
var layer = new mapnik.Layer(options.layerName);
layer.datasource = new mapnik.Datasource({
type: process.env.DB_TYPE,
dbname: process.env.DB_DATABASE,
table: options.layerName,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD
});
layer.styles = ['default'];
map.add_layer(layer);
return new Promise( (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);
console.log(`${vtile.getData().length} KB`);
resolve(vtile.getData());
});
});
};
module.exports = app;