birds-mpbx-gljs

Adding interactivity to your map (information pop-up and data clustering)

This tutorial will guide you to adding information popups to your map and improve the visual style of the data using clustering.

Displaying popup to show data information on click.


map.on('click', 'birds', function (e) {
var coordinates = e.features[0].geometry.coordinates.slice();
var description = e.features[0].properties.en_name;

while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
}

new mapboxgl.Popup()
.setLngLat(coordinates)
.setHTML(description)
.addTo(map);
});

The above code does the following: when a click event occurs on a feature in the birds layer, open a popup at the location of the feature, with description HTML from its properties.

Clustering overlapping points

Our current point styling looks cluttered at low zoom level, for example, there are a lot of overlapping points with a lot of bird sightings. We can improve the visuals of our map by adding clustering using the same data-driven styling capabilities of Mapbox GL JS.

map.addSource('birds', { type: 'geojson',
                             data: url,
                             cluster: true,
                             clusterMaxZoom: 12,
                             clusterRadius: 30 });

This activates the clustering option to your GeoJSON with a max zoom to cluster points at z12 and the radius of each cluster when clustering points.

map.addLayer({
      id: 'clusters',
      type: 'circle',
      source: 'birds',
      filter: ['has', 'point_count'],
      paint: {
        'circle-color': [
          'step',
          ['get', 'point_count'],
          '#51bbd6',50,
          '#f1f075',100,
          '#f28cb1'
        ],
        'circle-radius': [
          'step',
          ['get', 'point_count'],
          20,50,
          30,100,
          40
        ]
      }
    });

The above code uses the step expressions to style clustered points with three types of circles:

map.addLayer({
          id: 'unclustered-point',
          type: 'circle',
          source: 'birds',
          filter: ['!', ['has', 'point_count']],
          paint: {
            'circle-radius': {
              'base': 1.75,
              'stops': [
                [12, 3],
                [22, 180]
              ]
            },
            'circle-color': [
              'match', ['get', 'status'],
              'CR', '#fbb03b',
              'DD', '#223b53',
              'EN', '#e55e5e',
              'Nt', '#3bb2d0',
              'VUL', '#fb9a99',
              /* other */
              '#000'
            ]
          }
        });

      });
      map.on('click', 'unclustered-point', function(e) {
        var coordinates = e.features[0].geometry.coordinates.slice();
        var description = e.features[0].properties.en_name;

        while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
          coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
        }

        new mapboxgl.Popup()
          .setLngLat(coordinates)
          .setHTML(description)
          .addTo(map);
      });

Congratulations! You have finished your map! Inspect your code and experiment with different circle-* options to make your clusters and symbols more appealing.

See also