Отображение количества точек в Mapbox GL JS опирается на механизм кластеризации источников данных, при котором множество близко расположенных объектов объединяется в один кластерный объект с агрегированными свойствами. Основной целью такого подхода является визуальное упрощение карты при больших объёмах данных и предоставление числовой информации о плотности распределения объектов.
Кластеризация включается на уровне источника данных GeoJSON. При этом библиотека автоматически группирует точки в кластеры в зависимости от масштаба карты и заданных параметров.
map.addSource('points', {
type: 'geojson',
data: 'points.geojson',
cluster: true,
clusterMaxZoom: 14,
clusterRadius: 50
});
Ключевые параметры:
Каждый кластер содержит автоматически сгенерированные свойства:
point_count — количество точек внутри кластераpoint_count_abbreviated — сокращённое отображение
количества (например, 1.2k)Для визуализации числа точек внутри кластера используется слой
символов (symbol layer) с текстовым полем, привязанным к
свойствам кластера.
map.addLayer({
id: 'cluster-count',
type: 'symbol',
source: 'points',
filter: ['has', 'point_count'],
layout: {
'text-field': ['get', 'point_count_abbreviated'],
'text-font': ['DIN Offc Pro Medium', 'Arial Unicode MS Bold'],
'text-size': 12
}
});
Здесь используется выражение
['get', 'point_count_abbreviated'], которое извлекает
агрегированное значение из кластера. Это позволяет автоматически
отображать сокращённые значения без дополнительной логики на стороне
приложения.
В случаях, когда требуется точное число объектов без сокращений,
применяется свойство point_count:
'text-field': ['get', 'point_count']
Разница между форматами заключается исключительно в визуальном представлении:
point_count — полное числоpoint_count_abbreviated — формат с суффиксами (k,
m)Количество точек часто дополняется визуальной дифференциацией
кластеров по размеру или цвету. Это реализуется через
circle layer, где стили зависят от значения
point_count.
map.addLayer({
id: 'clusters',
type: 'circle',
source: 'points',
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
]
}
});
Такая конструкция позволяет формировать многоуровневую визуализацию плотности данных:
Mapbox GL JS поддерживает создание пользовательских агрегированных
свойств через clusterProperties. Это позволяет вычислять
дополнительные метрики внутри кластера, например количество объектов по
категориям.
map.addSource('points', {
type: 'geojson',
data: 'points.geojson',
cluster: true,
clusterProperties: {
redCount: ['+', ['case', ['==', ['get', 'color'], 'red'], 1, 0]],
blueCount: ['+', ['case', ['==', ['get', 'color'], 'blue'], 1, 0]]
}
});
После этого новые свойства доступны аналогично
point_count:
'text-field': [
'concat',
'R: ', ['get', 'redCount'],
' B: ', ['get', 'blueCount']
]
Такой подход позволяет отображать не только общее количество точек, но и их внутреннюю структуру.
При работе с различными уровнями масштаба важно учитывать изменение плотности данных. Для этого используются выражения интерполяции и ступенчатые функции.
'text-size': [
'interpolate',
['linear'],
['zoom'],
5, 10,
10, 14,
15, 18
]
Это позволяет согласовать читаемость количества точек с масштабом карты, избегая перегрузки интерфейса на низких зумах.
Для корректного отображения количества точек необходимо разделять слои кластеров и одиночных объектов с помощью фильтров:
filter: ['!', ['has', 'point_count']]
Одиночные точки могут отображаться отдельно:
map.addLayer({
id: 'unclustered-point',
type: 'circle',
source: 'points',
filter: ['!', ['has', 'point_count']],
paint: {
'circle-color': '#11b4da',
'circle-radius': 6
}
});
Это разделение обеспечивает чистую визуальную структуру: кластеры показывают количество, а отдельные точки — конкретные объекты.
Кластеры динамически пересчитываются при изменении масштаба карты.
Это означает, что значение point_count не является
статичным и зависит от текущего уровня детализации.
При увеличении масштаба:
При уменьшении масштаба:
point_count увеличиваютсяПри работе с тысячами или миллионами точек кластеризация становится ключевым механизмом оптимизации. Основные аспекты:
Дополнительно используется:
map.addSource('points', {
type: 'geojson',
data: 'points.geojson',
cluster: true,
clusterRadius: 40,
clusterMaxZoom: 12
});
Меньший clusterRadius повышает детализацию, но
увеличивает количество кластеров, тогда как больший — наоборот.
Для улучшения читаемости чисел часто применяются форматированные выражения:
'text-field': [
'format',
['get', 'point_count'],
{ 'font-scale': 1.2 }
]
Это позволяет комбинировать стили текста и улучшать визуальную иерархию числовых значений внутри кластеров.
Кластеры могут быть использованы как интерактивные элементы. При клике возможно получение информации о количестве объектов:
map.on('click', 'clusters', (e) => {
const features = map.queryRenderedFeatures(e.point, {
layers: ['clusters']
});
const clusterId = features[0].properties.cluster_id;
const source = map.getSource('points');
source.getClusterExpansionZoom(clusterId, (err, zoom) => {
map.easeTo({
center: features[0].geometry.coordinates,
zoom: zoom
});
});
});
Хотя этот механизм не изменяет отображение количества точек напрямую, он усиливает его функциональную роль в навигации по данным.