5

I'm new in MapBox GL Js and I want to call a big GeoJSON file over https and display it to the map. I think that calling vector Tile is the best way to do that, I found some tutorials that show how to convert your GeoJSON data to Vector Tile but on Server Side or upload it to the MapBox Style but my GeoJSON file is frequently changing. So I found this solution is a new JavaScript library called geojson-vt, describing how to convert a huge GeoJSON files to vector tile on the fly (Client Side) with crazy fast, It's seems like what I'm looking for, BUT !!, How can I integrate it to the MapBox GL JS for calling the layer ??

Blocking on How can I add Layer using Mapbox GL JS with the following result : var tileIndex = geojsonvt(MyGeoJSON); var tile = tileIndex.getTile(z, x, y);

... Or I just didn't get it ! Please somebody helps or can propose some other solution for my problem.

Elkadiri Imad
  • 53
  • 1
  • 4

3 Answers3

1

I'd recommend using Deck.gl GeoJSON Layer. Here's an example:

<html>
  <head>
    <title>deck.gl GeoJsonLayer (Polygon) Example</title>

    <script src="https://unpkg.com/deck.gl@^8.0.0/dist.min.js"></script>
    <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.4.0/mapbox-gl.js"></script>

    <style type="text/css">
      body {
        width: 100vw;
        height: 100vh;
        margin: 0;
        overflow: hidden;
      }
      .deck-tooltip {
        font-family: Helvetica, Arial, sans-serif;
        padding: 6px !important;
        margin: 8px;
        max-width: 300px;
        font-size: 10px;
      }
    </style>
  </head>

  <body>
  </body>

  <script type="text/javascript">

    const {DeckGL, GeoJsonLayer} = deck;

    const COLOR_SCALE = [
      // negative
      [65, 182, 196],
      [127, 205, 187],
      [199, 233, 180],
      [237, 248, 177],

      // positive
      [255, 255, 204],
      [255, 237, 160],
      [254, 217, 118],
      [254, 178, 76],
      [253, 141, 60],
      [252, 78, 42],
      [227, 26, 28],
      [189, 0, 38],
      [128, 0, 38]
    ];

    const geojsonLayer = new GeoJsonLayer({
      data: 'https://raw.githubusercontent.com/uber-common/deck.gl-data/master/examples/geojson/vancouver-blocks.json',
      opacity: 0.8,
      stroked: false,
      filled: true,
      extruded: true,
      wireframe: true,

      getElevation: f => Math.sqrt(f.properties.valuePerSqm) * 10,
      getFillColor: f => colorScale(f.properties.growth),
      getLineColor: [255, 255, 255],

      pickable: true
    });

    new DeckGL({
      mapboxApiAccessToken: '<mapbox-access-token>',
      mapStyle: 'mapbox://styles/mapbox/light-v9',
      initialViewState: {
        latitude: 49.254,
        longitude: -123.13,
        zoom: 11,
        maxZoom: 16,
        pitch: 45
      },
      controller: true,
      layers: [geojsonLayer],
      getTooltip
    });

    function colorScale(x) {
      const i = Math.round(x * 7) + 4;
      if (x < 0) {
        return COLOR_SCALE[i] || COLOR_SCALE[0];
      }
      return COLOR_SCALE[i] || COLOR_SCALE[COLOR_SCALE.length - 1];
    }

    function getTooltip({object}) {
      return object && `Average Property Value
        ${object.properties.valuePerSqm}
        Growth
        ${Math.round(object.properties.growth * 100)}`;
    }

  </script>
</html>

Atrribution here.

Joe - GMapsBook.com
  • 15,787
  • 4
  • 23
  • 68
  • I haven't used Deck GL with Mapbox before. What are the benefits of using a DeckGL GeoJSON layer as opposed to the native Mapbox-GL-JS GeoJSON source and fill layer? – Steve Bennett Apr 22 '20 at 23:21
  • One of the reasons would be: `For example, a deck.gl GeoJSON layer can be inserted in between Mapbox’s base geography and label layers, so that filled polygons no longer hamper readability of the map.` More at https://eng.uber.com/uber-visualization-mapbox/ – Joe - GMapsBook.com Apr 23 '20 at 08:17
  • You can do that with native Mapbox-GL-JS layers too? – Steve Bennett Apr 23 '20 at 08:50
  • Not sure. AFAIK the GL-JS layers are essentially a subset of what deck is capable of. I use deck mostly w/ gmaps, not mapbox, and there's no "native" option there. – Joe - GMapsBook.com Apr 23 '20 at 08:56
1

You don't need to worry about geojson-vt. Mapbox-GL-JS does that internally. So you can just follow the standard documentation for loading a GeoJSON layer.

If your GeoJSON is really huge, then probably the limiting factor will be network transfer, which means you really need to be serving server-side vector tiles.

Steve Bennett
  • 114,604
  • 39
  • 168
  • 219
  • Thank you Steve your're right geojson-vt already include in Mapbox-GL-JS. But my problem is still persis. The size of GeoJSON file is like 0.5GB loading it to the map as layer make my browser freezing. So I server it from my GeoServer like a Vector layer (WMTS) but it still so slow.Then I saw [that solution](https://docs.mapbox.com/help/troubleshooting/large-data-tippecanoe) converting a GeoJSON(761Mb) file to a MBTiles(4.7Mb) file then upload it BUT the problem is my Data is changing every minute. Is there any other solution or some suggestion please share it with me. – Elkadiri Imad Apr 22 '20 at 17:07
  • Yep, 500MB is too big. There are obviously many possible solutions, but that's a bit too broad for a StackOverflow question. Generally they involve server-side solutions. You might be better off asking at gis.stackexchange.com – Steve Bennett Apr 22 '20 at 23:13
  • There's also commercial providers of server-side tiling like CARTO: https://carto.com/developers/carto-js/examples/#example-server-tile-aggregation-with-cluster-of-points – Joe - GMapsBook.com Apr 23 '20 at 08:21
  • Or, um, Mapbox. – Steve Bennett Apr 23 '20 at 08:50
  • Hey @ElkadiriImad, i am facing the same issue. i need to render a huge geojson file in mapbox and it freezes my browser. Did you find any solution for that? Thanks, Daniela – Daniela Jul 24 '20 at 13:21
  • Don't load the geojson directly into the browser. Generate vector tiles and host them somewhere such as Mapbox, Maptiler Cloud, etc. – Steve Bennett Jul 26 '20 at 06:20
  • Hey @Daniela sorry for the late reply... No need to load all the GeoJSON file.. For my case I transfet the file into a table in Database then I configure the wabservice (GeoServer) to read from this table finally i call the Geometry and it alphanumeric from MapBox via the webservice in a Vector Tiles Format. Hope this will help you ! – Elkadiri Imad Sep 02 '20 at 11:53
  • @ElkadiriImad I am wondering how fast it is when connecting it with GeoServer. On your above comment, what do you mean by alphanumeric from MapBox? – wondim Sep 05 '20 at 10:50
0

Oh, man, I've spent 8 days, researching that. The solution is:

var vtpbf = require('vt-pbf');
var geojsonVt = require('geojson-vt');

var orig = JSON.parse(fs.readFileSync(__dirname + 'myjson.json'))
var tileindex = geojsonVt(orig)
var tile = tileindex.getTile(x, y, z); // mapbox sends automatic request to the server, and give x, y , z

// pass in an object mapping layername -> tile object
var buff = vtpbf.fromGeojsonVt({ 'geojsonLayer': tile });

I've sent the result to the frontend, it works like Mapbox API. For the details check: https://github.com/mapbox/vt-pbf

And from the Mapbox side:

            const  source = {
                type    : 'vector',
                'tiles' : [ 'http://localhost:1234/county?z={z}&x={x}&y={y}' ],
                minzoom : 0,
                maxzoom : 14
            };

            map.addSource('source', source );
            map.addLayer({
                'id'           : 'source',
                'type'         : 'fill',
                'source'       : 'source',
                'source-layer' : 'tiles-sequences',
                'fill-color'   : '#00ffff'
            });