ScatterplotLayer

ScatterplotLayer — один из наиболее востребованных слоёв библиотеки Deck.gl, предназначенный для отображения большого количества точечных объектов на карте или в произвольной координатной системе. Каждый объект визуализируется в виде круга, размеры, цвет, прозрачность и другие характеристики которого могут вычисляться динамически на основе данных.

Слой особенно эффективен для:

  • визуализации географических точек;
  • отображения датчиков и IoT-устройств;
  • анализа плотности распределения объектов;
  • отображения местоположений пользователей;
  • визуализации статистических показателей по координатам;
  • работы с десятками и сотнями тысяч точек благодаря GPU-ускорению.

ScatterplotLayer относится к числу базовых слоёв Deck.gl и часто используется как отправная точка при построении геопространственных приложений.


Подключение слоя

После установки Deck.gl слой импортируется следующим образом:

import {ScatterplotLayer} from '@deck.gl/layers';

Создание экземпляра слоя:

const layer = new ScatterplotLayer({
  id: 'scatter-layer',
  data: []
});

Каждый слой должен иметь уникальный идентификатор через свойство id.


Структура данных

Минимальный набор данных обычно представляет собой массив объектов с координатами.

const data = [
  {
    position: [37.6173, 55.7558],
    name: 'Москва'
  },
  {
    position: [30.3141, 59.9386],
    name: 'Санкт-Петербург'
  }
];

Для работы слоя необходимо указать способ получения координат.

const layer = new ScatterplotLayer({
  id: 'cities',
  data,
  getPosition: d => d.position
});

Метод getPosition вызывается для каждого элемента массива данных.


Координаты объектов

Формат координат

ScatterplotLayer ожидает массив:

[longitude, latitude]

Пример:

[37.6173, 55.7558]

Также допускается использование высоты:

[37.6173, 55.7558, 100]

Третье значение интерпретируется как высота над поверхностью.


Настройка радиуса точек

Базовый радиус

Размер круга задаётся через свойство getRadius.

const layer = new ScatterplotLayer({
  id: 'cities',
  data,
  getPosition: d => d.position,
  getRadius: 1000
});

В данном случае все точки будут иметь одинаковый радиус.


Динамический радиус

Чаще радиус зависит от данных.

const layer = new ScatterplotLayer({
  id: 'population',
  data,
  getPosition: d => d.position,
  getRadius: d => d.population
});

Пример структуры объекта:

{
  position: [37.6173, 55.7558],
  population: 12000
}

Каждая точка получит собственный размер.


Масштабирование радиуса

Для изменения общего масштаба используется параметр radiusScale.

const layer = new ScatterplotLayer({
  id: 'population',
  data,
  getPosition: d => d.position,
  getRadius: d => d.population,
  radiusScale: 10
});

Итоговый радиус вычисляется как:

getRadius × radiusScale

Ограничение размеров

Слишком большие или слишком маленькие значения можно ограничить.

const layer = new ScatterplotLayer({
  id: 'population',
  data,
  getPosition: d => d.position,
  getRadius: d => d.population,
  radiusMinPixels: 2,
  radiusMaxPixels: 50
});

Параметры:

Свойство Назначение
radiusMinPixels Минимальный размер точки
radiusMaxPixels Максимальный размер точки

Цвет точек

Фиксированный цвет

Цвет задаётся массивом RGBA.

const layer = new ScatterplotLayer({
  id: 'points',
  data,
  getPosition: d => d.position,
  getFillColor: [255, 0, 0]
});

Красный цвет для всех объектов.


Использование прозрачности

getFillColor: [255, 0, 0, 120]

Значения:

R = 255
G = 0
B = 0
A = 120

Альфа-канал находится в диапазоне от 0 до 255.


Динамическая окраска

Цвет может зависеть от характеристик объекта.

const layer = new ScatterplotLayer({
  id: 'temperature',
  data,
  getPosition: d => d.position,
  getFillColor: d =>
    d.temperature > 30
      ? [255, 0, 0]
      : [0, 0, 255]
});

Красный цвет для высоких температур, синий — для остальных.


Контур точек

ScatterplotLayer способен рисовать не только заливку, но и границу.

Включение контура

const layer = new ScatterplotLayer({
  id: 'points',
  data,
  stroked: true
});

Цвет контура

const layer = new ScatterplotLayer({
  id: 'points',
  data,
  stroked: true,
  getLineColor: [0, 0, 0]
});

Черная обводка вокруг точек.


Толщина контура

const layer = new ScatterplotLayer({
  id: 'points',
  data,
  stroked: true,
  lineWidthMinPixels: 2
});

Динамический контур

const layer = new ScatterplotLayer({
  id: 'points',
  data,
  stroked: true,
  getLineColor: d =>
    d.active
      ? [0, 255, 0]
      : [255, 0, 0]
});

Использование пикселей и метров

Одной из важных особенностей ScatterplotLayer является возможность задавать размеры в разных единицах измерения.

Радиус в метрах

По умолчанию:

radiusUnits: 'meters'

Пример:

getRadius: 1000

Радиус составляет один километр.


Радиус в пикселях

radiusUnits: 'pixels'

Полный пример:

const layer = new ScatterplotLayer({
  id: 'points',
  data,
  getPosition: d => d.position,
  radiusUnits: 'pixels',
  getRadius: 10
});

Размер остаётся одинаковым независимо от масштаба карты.


Интерактивность

Поддержка выбора объектов

Для обработки событий необходимо включить возможность выбора.

pickable: true

Обработка клика

const layer = new ScatterplotLayer({
  id: 'points',
  data,
  pickable: true,

  onClick: info => {
    console.log(info.object);
  }
});

Объект info содержит данные выбранной точки.


Наведение мыши

const layer = new ScatterplotLayer({
  id: 'points',
  data,
  pickable: true,

  onHover: info => {
    console.log(info.object);
  }
});

Событие вызывается при перемещении курсора.


Информация объекта выбора

Deck.gl формирует специальный объект выбора.

onClick: info => {
  console.log(info);
}

Основные поля:

Поле Описание
object Исходный объект данных
x Координата курсора по X
y Координата курсора по Y
coordinate Географические координаты
index Индекс элемента
layer Слой

Пример:

{
  object: {
    name: 'Москва'
  },
  index: 0
}

Подсказки (Tooltips)

Для отображения информации обычно используется свойство getTooltip.

new Deck({
  layers: [layer],

  getTooltip: ({object}) =>
    object && {
      text: object.name
    }
});

Поддержка высоты

ScatterplotLayer способен отображать точки в трёхмерном пространстве.

Данные:

{
  position: [37.6173, 55.7558, 1000]
}

Слой:

const layer = new ScatterplotLayer({
  id: '3d-points',
  data,
  getPosition: d => d.position
});

Высота будет учитываться при использовании 3D-вида карты.


Параметр billboard

По умолчанию круги располагаются в плоскости карты.

billboard: false

При включении:

billboard: true

круги всегда поворачиваются лицом к камере.

Это особенно полезно при сильном наклоне карты.


Использование обновлений данных

Deck.gl отслеживает изменения данных и обновляет GPU-буферы.

layer = new ScatterplotLayer({
  id: 'points',
  data: newData,
  getPosition: d => d.position
});

При изменении массива происходит автоматический пересчёт атрибутов.


Оптимизация вычислений

Избегание создания новых функций

Плохо:

render() {
  return new ScatterplotLayer({
    getRadius: d => d.value
  });
}

Лучше:

const getRadius = d => d.value;

new ScatterplotLayer({
  getRadius
});

Это уменьшает количество лишних обновлений.


Использование updateTriggers

Когда вычисления зависят от внешних переменных, следует явно указывать триггеры обновления.

const scale = 2;

const layer = new ScatterplotLayer({
  id: 'points',

  getRadius: d => d.value * scale,

  updateTriggers: {
    getRadius: scale
  }
});

При изменении scale слой автоматически пересчитает размеры.


Анимация размеров

Размеры могут плавно изменяться при обновлении данных.

const layer = new ScatterplotLayer({
  id: 'animated',
  data,

  transitions: {
    getRadius: 500
  },

  getRadius: d => d.value
});

Длительность анимации — 500 миллисекунд.


Анимация цвета

const layer = new ScatterplotLayer({
  id: 'animated-colors',
  data,

  transitions: {
    getFillColor: 1000
  },

  getFillColor: d => d.color
});

Цвет будет плавно интерполироваться.


Работа с большими объёмами данных

ScatterplotLayer разработан с расчётом на высокую производительность.

Особенности реализации:

  • вычисления выполняются на GPU;
  • используется пакетная обработка атрибутов;
  • поддерживаются сотни тысяч объектов;
  • минимизируется количество обращений к DOM;
  • применяется эффективный механизм picking.

Пример генерации большого набора данных:

const data = Array.from(
  {length: 100000},
  (_, i) => ({
    position: [
      30 + Math.random(),
      60 + Math.random()
    ],
    value: Math.random() * 100
  })
);

Слой:

const layer = new ScatterplotLayer({
  id: 'large-dataset',
  data,
  getPosition: d => d.position,
  getRadius: d => d.value,
  pickable: true
});

Практический пример: карта населения

const layer = new ScatterplotLayer({
  id: 'population',

  data: cities,

  pickable: true,

  getPosition: d => d.coordinates,

  getRadius: d => d.population,

  radiusScale: 0.02,

  radiusMinPixels: 2,

  getFillColor: d => {
    if (d.population > 1000000) {
      return [255, 0, 0];
    }

    if (d.population > 500000) {
      return [255, 165, 0];
    }

    return [0, 128, 255];
  },

  onClick: info => {
    console.log(info.object);
  }
});

В таком сценарии:

  • координаты определяют положение города;
  • радиус отображает численность населения;
  • цвет показывает категорию населённого пункта;
  • клик позволяет получить подробную информацию.

Основные свойства ScatterplotLayer

Свойство Назначение
data Источник данных
getPosition Координаты точки
getRadius Радиус объекта
getFillColor Цвет заливки
getLineColor Цвет контура
stroked Включение обводки
filled Включение заливки
radiusScale Масштаб радиуса
radiusUnits Единицы измерения
radiusMinPixels Минимальный размер
radiusMaxPixels Максимальный размер
lineWidthUnits Единицы ширины линии
lineWidthMinPixels Минимальная ширина контура
lineWidthMaxPixels Максимальная ширина контура
pickable Возможность выбора
autoHighlight Автоматическая подсветка
highlightColor Цвет подсветки
billboard Поворот к камере
transitions Анимация изменений
updateTriggers Контроль обновлений

Автоматическая подсветка объектов

Deck.gl может автоматически выделять объект под курсором.

const layer = new ScatterplotLayer({
  id: 'points',
  data,

  pickable: true,

  autoHighlight: true
});

Настройка цвета подсветки

const layer = new ScatterplotLayer({
  id: 'points',
  data,

  pickable: true,

  autoHighlight: true,

  highlightColor: [255, 255, 0, 120]
});

При наведении точка будет подсвечиваться полупрозрачным жёлтым цветом.


Сочетание ScatterplotLayer с другими слоями

ScatterplotLayer часто используется совместно с другими слоями Deck.gl:

  • IconLayer для отображения иконок;
  • TextLayer для подписей;
  • HeatmapLayer для тепловых карт;
  • HexagonLayer для агрегации точек;
  • GeoJsonLayer для отображения полигонов;
  • ColumnLayer для объёмной визуализации.

Пример комбинирования:

const layers = [
  scatterLayer,
  textLayer,
  geoJsonLayer
];

Такой подход позволяет строить сложные геоаналитические интерфейсы, где ScatterplotLayer отвечает за быстрое и эффективное отображение большого количества точечных объектов с гибкой настройкой размеров, цветов, интерактивности и анимации.