block by jczaplew 2e2a243dbe8d4dd8a075e75f3a4366d5

Supercluser + tilestrata + Mapbox GL JS

Full Screen

index.js

const turfRandom = require('@turf/random')
const supercluster = require('supercluster')
const vtpbf = require('vt-pbf')
const tilestrata = require('tilestrata')

// generate random points
let points = turfRandom('points', 10000, {
  bbox: [-175, -85, 175, 85]
})

// Assign an ID for testing
points.features = points.features.map(p => {
  p.properties.p_id = Math.random().toString(36).slice(2)
  return p
})

// Initialize the index and load the points
let index = supercluster({
  radius: 40,
  maxZoom: 16,
  extent: 512,
  log: true
}).load(points.features)

// Tilestrata provider for querying the index
let clusterProvider = function(options) {
  return {
    name: 'cluster',
    init: (server, callback) => {
      callback()
    },
    serve: (server, tile, callback) => {
      callback(null, vtpbf.fromGeojsonVt({ 'clusters': index.getTile(tile.z, tile.x, tile.y) }), {
        'Access-Control-Allow-Origin': '*',
        'Content-Type':' application/x-protobuf'
      })
    },
    destroy: (server, callback) => {

    }
  }
}

let strata = tilestrata()

strata.layer('points')
      .route('tile.mvt')
      .use(clusterProvider())

strata.listen(7171)

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8' />
    <title></title>
    <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
    <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.39.1/mapbox-gl.js'></script>
    <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.39.1/mapbox-gl.css' rel='stylesheet' />
    <style>
        body { margin:0; padding:0; }
        #map { position:absolute; top:0; bottom:0; width:100%; }
    </style>
</head>
<body>

<div id='map'></div>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoiamN6YXBsZXdza2kiLCJhIjoiWnQxSC01USJ9.oleZzfREJUKAK1TMeCD0bg';
var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/streets-v9',
    center: [-106, 51],
    zoom: 3
})

map.on('load', () => {
  this.map.addSource('clusters', {
    "type": "vector",
    "tiles": ["//localhost:7171/points/{z}/{x}/{y}/tile.mvt"],
    "tileSize": 512
  })

  this.map.addLayer({
    "id": "cluster-layer",
    "type": "circle",
    "source": "clusters",
    "source-layer": "clusters",
    "paint": {
      'circle-color': '#08519c',
      'circle-radius': 2
    }
  })
})
</script>

</body>
</html>

package.json

{
  "name": "supercluster-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "author": "",
  "license": "CCO",
  "dependencies": {
    "@turf/random": "^4.5.2",
    "supercluster": "^2.3.0",
    "tilestrata": "^2.0.6",
    "vt-pbf": "^2.1.4"
  }
}