4

I want to use Mapbox GL to render vector tiles that I am generating from PostGIS requests. I have built a tile server using Mapnik, sphericalmecator, and pg plugins for npm. I added the tile endpoint to the stylesheet for Mapbox GL, and have confirmed that the correct tiles are requested, but the tiles are not rendered on the map. I used the same backend for a leaflet plugin and it works correctly, so I'm not sure I have to change the backend. Any advice is appreciated. Code is below.

This is the index.html file that I am loading.

  var map = new mapboxgl.Map({
    container: 'map',
    style: 'outdoors-v7.json',
    center: [47.4333, 19.2500],
    zoom: 9
  });
  map.on('style.load', function() {
    map.addSource("parcelLayer", {
      "type": "vector",
      "tiles": ["http://localhost:5001/data/city/lots/budapest/{z}/{x}/{y}.pbf"],
    });

    map.addLayer({
      "id": "parcelLayer",
      "type": "fill",
      "source": "parcelLayer",
      "layout": {
        "visibility": "visible"
      },
      "paint": {
        "fill-color": '#ff0000',
        "fill-opacity": 1
      }
    });
});

This is the routes that the map is calling.

var express = require('express');
var router = express.Router();
var conString = require('../../database').conString;
var pg = require('pg');
var SphericalMercator = require('sphericalmercator');
var mapnik = require('mapnik');
var zlib = require('zlib');

mapnik.register_default_fonts();
mapnik.register_default_input_plugins();

var mercator = new SphericalMercator({
  size: 256
 });

router.get('/:city_name/:z/:x/:y.pbf', function(req, res) {

  var city_name = req.params.city_name;
  var bbox = mercator.bbox(
    +req.params.x,
    +req.params.y,
    +req.params.z,
    false,
    '4326'
  );

  pg.connect(conString, function(err, client, done){
    var config_object = {
      'medellin' : {
         'attributes': ['cobama', 'subtipo_lote', 'tipo_lote', 'estrato', 'zona', 'usopredial', 'npisos', 'calificacion']
       },
      'lima' : {
         'attributes': ['objectid', 'id_lote', 'tip_uso', 'id_dist', 'estado']
      },
      'budapest': {
         'attributes': ['id', 'tags']
      }
    };
    var handleError = function(err) {
      // no error occurred, continue with the request
      if(!err) return false;
      // An error occurred, remove the client from the connection pool.
      // A truthy value passed to done will remove the connection from the pool
      // instead of simply returning it to be reused.
      // In this case, if we have successfully received a client (truthy)
      // then it will be removed from the pool.
      if(client){
        done(client);
      }
      console.log(err);
      // res.writeHead(500, {'content-type': 'text/plain'});
      // res.end('An error occurred');
      return true;
    };
    // handle an error from the connection
    if(handleError(err)) return;
    if(city_name === 'medellin' || city_name === 'lima' || city_name === 'budapest'){
      client.query('SELECT row_to_json(fc) FROM ( SELECT "FeatureCollection" As type, array_to_json(array_agg(f)) As features FROM (SELECT 'Feature' As type, ST_AsGeoJSON(lg.wkb_geometry)::json As geometry, row_to_json((SELECT l FROM (SELECT ' + config_object[city_name]['attributes'].join(', ') + ' ) As l )) As properties FROM ' + city_name + '_parcels As lg WHERE st_intersects(lg.wkb_geometry, st_makeenvelope(' + bbox.toString() + ', 4326) ) ) As f )  As fc', function(err, result){
        if (err) {
          console.log('error in the query');
          return console.error('error running query', err);
        }
        // handle an error from the connection
        if(handleError(err)) return;
        var vtile = new mapnik.VectorTile(+req.params.z, +req.params.x, +req.params.y);
        if( (typeof result.rows[0] !== 'undefined')  && (result.rows[0].row_to_json.features !== null )){
          try {
            vtile.addGeoJSON(JSON.stringify(result.rows[0].row_to_json), 'lots');
            console.log(result.rows[0].row_to_json.features[0]);
          } catch (e) {
            console.log('came back with an error');
            console.log(e);
          }
        }
        res.setHeader('Content-Encoding', 'deflate');
        res.setHeader('Content-Type', 'application/x-protobuf');
        zlib.deflate(vtile.getData(), function(err, pbf) {
          done();
          // res.writeHead(200);
          res.send(pbf);
        });    
      });
    }
  });
});

Please ask any other questions you might have.

4

0 回答 0