Clusters
Visualize dense point data with dynamic clustering. Cluster circles are color-coded and sized by count. Click a cluster to zoom in.
gts
import type { MapMouseEvent } from 'maplibre-gl';
import MapLibreGL from 'ember-maplibre-gl/components/maplibre-gl';
const mapOptions = {
style: 'https://tiles.openfreemap.org/styles/bright',
center: [-103.59, 40.66] as [number, number],
zoom: 3,
};
const source = {
type: 'geojson' as const,
data: 'https://maplibre.org/maplibre-gl-js/docs/assets/earthquakes.geojson',
cluster: true,
clusterMaxZoom: 14,
clusterRadius: 50,
};
const clusterLayer = {
id: 'clusters',
type: 'circle' as const,
filter: ['has', 'point_count'],
paint: {
'circle-color': [
'step', ['get', 'point_count'],
'#51bbd6', 100,
'#f1f075', 750,
'#f28cb1',
],
'circle-radius': [
'step', ['get', 'point_count'],
20, 100,
30, 750,
40,
],
},
};
const clusterCountLayer = {
type: 'symbol' as const,
filter: ['has', 'point_count'],
layout: {
'text-field': '{point_count_abbreviated}',
'text-size': 12,
},
};
const pointLayer = {
id: 'unclustered-point',
type: 'circle' as const,
filter: ['!', ['has', 'point_count']],
paint: {
'circle-color': '#11b4da',
'circle-radius': 5,
'circle-stroke-width': 1.5,
'circle-stroke-color': '#fff',
},
};
const onClusterClick = (e: MapMouseEvent) => {
const map = e.target;
const features = map.queryRenderedFeatures(e.point, {
layers: ['clusters'],
});
if (!features.length) return;
const clusterId = features[0].properties.cluster_id;
(map.getSource(features[0].source) as any).getClusterExpansionZoom(clusterId)
.then((zoom: number) => {
map.easeTo({ center: (features[0].geometry as any).coordinates, zoom });
});
};
<template>
<MapLibreGL
@initOptions={{mapOptions}}
style="height: 500px; width: 100%; border-radius: 8px; cursor: pointer;"
as |map|>
<map.source @options={{source}} as |source|>
<source.layer @options={{clusterLayer}} />
<source.layer @options={{clusterCountLayer}} />
<source.layer @options={{pointLayer}} />
</map.source>
<map.on @event="click" @layerId="clusters" @action={{onClusterClick}} />
</MapLibreGL>
</template>Based on the MapLibre GL JS Cluster example.