ArcLayer — один из базовых слоёв библиотеки Deck.gl, предназначенный для визуализации связей между двумя географическими точками. Каждая связь отображается в виде дуги, соединяющей исходную и конечную координаты. Такой способ представления данных широко используется для отображения транспортных маршрутов, миграционных потоков, логистических цепочек, финансовых транзакций, телекоммуникационных соединений и любых других объектов, имеющих направление перемещения между двумя местами.
Главная особенность слоя заключается в том, что линии отображаются не как обычные прямые сегменты, а как визуально выразительные дуги, поднимающиеся над поверхностью карты. Благодаря этому большие наборы связей становятся более наглядными и легче воспринимаются.
ArcLayer входит в пакет @deck.gl/layers.
npm install @deck.gl/core
npm install @deck.gl/layers
Импорт слоя:
import {ArcLayer} from '@deck.gl/layers';
Создание простейшего слоя:
const arcLayer = new ArcLayer({
id: 'arc-layer',
data: [
{
from: [37.618423, 55.751244],
to: [30.335099, 59.934280]
}
],
getSourcePosition: d => d.from,
getTargetPosition: d => d.to,
getSourceColor: [0, 128, 255],
getTargetColor: [255, 0, 0],
getWidth: 3
});
В данном примере отображается одна дуга между Москвой и Санкт-Петербургом.
Каждый объект данных должен содержать информацию о начальной и конечной точке.
Простейшая структура:
[
{
source: [37.618423, 55.751244],
target: [30.335099, 59.934280]
}
]
Использование с ArcLayer:
new ArcLayer({
data,
getSourcePosition: d => d.source,
getTargetPosition: d => d.target
});
Более реалистичный вариант:
[
{
cityFrom: "Москва",
cityTo: "Берлин",
source: [37.618423, 55.751244],
target: [13.4050, 52.5200],
passengers: 12000,
distance: 1600
}
]
Такой формат позволяет использовать дополнительные свойства для настройки толщины, цвета и других параметров визуализации.
Определяет координаты начала дуги.
getSourcePosition: d => d.source
Возвращаемое значение:
[longitude, latitude]
или
[longitude, latitude, altitude]
Пример:
getSourcePosition: d => [
d.lon,
d.lat
]
Определяет координаты конечной точки.
getTargetPosition: d => d.target
Пример:
getTargetPosition: d => [
d.destinationLon,
d.destinationLat
]
Для каждой записи ArcLayer строит дугу между результатами этих двух функций.
Одной из самых полезных возможностей ArcLayer является раздельное оформление начальной и конечной стороны.
Цвет начала линии.
getSourceColor: [0, 128, 255]
Либо динамически:
getSourceColor: d =>
d.type === "domestic"
? [0, 200, 0]
: [255, 120, 0]
Цвет конца линии.
getTargetColor: [255, 0, 0]
Пример создания цветового градиента:
new ArcLayer({
data,
getSourceColor: [0, 255, 255],
getTargetColor: [255, 0, 255]
});
Визуально дуга будет плавно менять цвет по направлению движения.
Определяет толщину линии.
Фиксированное значение:
getWidth: 2
Зависимость от данных:
getWidth: d => d.passengers / 1000
Например:
new ArcLayer({
data,
getWidth: d => Math.sqrt(d.volume)
});
Использование квадратного корня позволяет избежать слишком большого разброса толщин.
Глобальный множитель толщины.
widthScale: 5
Итоговая ширина:
getWidth × widthScale
Пример:
new ArcLayer({
getWidth: d => d.flow,
widthScale: 0.1
});
Минимальная ширина в пикселях.
widthMinPixels: 2
Даже при сильном уменьшении масштаба карты линия останется различимой.
Максимальная толщина.
widthMaxPixels: 20
Полезно при работе с очень большими значениями данных.
ArcLayer автоматически формирует кривую между двумя точками.
Высота зависит от:
Чем дальше расположены объекты, тем выше обычно отображается дуга.
Например:
{
source: [37.6, 55.7],
target: [139.6, 35.6]
}
Дуга между Москвой и Токио будет значительно выше, чем между двумя соседними городами.
Наиболее эффектно ArcLayer выглядит при использовании карты с наклоном.
Пример настроек камеры:
const INITIAL_VIEW_STATE = {
longitude: 30,
latitude: 50,
zoom: 3,
pitch: 45,
bearing: 0
};
Параметр:
pitch: 45
создаёт трёхмерный эффект подъёма дуг над поверхностью карты.
Типичный сценарий — отображение потоков между регионами.
Исходные данные:
[
{
source: [2.3522, 48.8566],
target: [13.4050, 52.5200],
flow: 25000
},
{
source: [-0.1276, 51.5072],
target: [13.4050, 52.5200],
flow: 18000
}
]
Настройка:
new ArcLayer({
data,
getSourcePosition: d => d.source,
getTargetPosition: d => d.target,
getWidth: d => d.flow,
widthScale: 0.0002
});
Чем больше поток, тем толще отображается дуга.
RGBA-массивы позволяют задавать альфа-канал.
Пример:
getSourceColor: [0, 128, 255, 100],
getTargetColor: [255, 0, 0, 100]
Полупрозрачность помогает уменьшить визуальную перегрузку при отображении тысяч связей одновременно.
ArcLayer поддерживает все стандартные механизмы взаимодействия Deck.gl.
Включение выбора объектов:
pickable: true
Обработка наведения:
onHover: info => {
console.log(info.object);
}
Обработка клика:
onClick: info => {
console.log(info.object);
}
Полный пример:
new ArcLayer({
data,
pickable: true,
onClick: ({object}) => {
if (object) {
console.log(object.cityFrom);
}
}
});
Часто ArcLayer используется совместно с tooltip.
Настройка Deck:
const deck = new Deck({
layers: [arcLayer],
getTooltip: ({object}) =>
object && {
text: `
Маршрут: ${object.cityFrom} → ${object.cityTo}
Пассажиры: ${object.passengers}
`
}
});
При наведении отображается информация о конкретной связи.
Deck.gl автоматически отслеживает изменение атрибутов.
Пример плавного изменения толщины:
new ArcLayer({
data,
getWidth: d => d.value,
transitions: {
getWidth: 1000
}
});
Продолжительность:
1000
означает одну секунду.
Изменение цвета также может быть анимировано.
transitions: {
getSourceColor: 500,
getTargetColor: 500
}
Применение:
new ArcLayer({
data,
getSourceColor: d => d.sourceColor,
getTargetColor: d => d.targetColor,
transitions: {
getSourceColor: 800,
getTargetColor: 800
}
});
ArcLayer оптимизирован для GPU-рендеринга и способен отображать десятки тысяч связей одновременно.
Практические рекомендации:
Плохо:
getWidth: d => {
return complicatedCalculation(d);
}
Лучше:
const preparedData = data.map(item => ({
...item,
width: complicatedCalculation(item)
}));
getWidth: d => d.width
ArcLayer редко используется изолированно.
Наиболее распространённые комбинации:
Точки обозначают узлы сети, дуги показывают связи.
layers: [
scatterplotLayer,
arcLayer
]
Названия городов и соединяющие маршруты.
layers: [
textLayer,
arcLayer
]
Отображение стран или регионов вместе с потоками между ними.
layers: [
geoJsonLayer,
arcLayer
]
Такой подход часто используется для визуализации миграции населения, грузоперевозок и международной торговли.
| Возможность | ArcLayer | LineLayer |
|---|---|---|
| Прямая линия | Нет | Да |
| Дуга | Да | Нет |
| Раздельные цвета начала и конца | Да | Ограниченно |
| Выраженный 3D-эффект | Да | Нет |
| Визуализация потоков | Отлично | Удовлетворительно |
| Производительность | Высокая | Высокая |
ArcLayer предпочтителен для отображения направленных связей между удалёнными объектами, тогда как LineLayer больше подходит для геометрически точных линейных объектов.
import {Deck} from '@deck.gl/core';
import {ArcLayer} from '@deck.gl/layers';
const data = [
{
source: [37.618423, 55.751244],
target: [13.4050, 52.5200],
passengers: 12000
},
{
source: [37.618423, 55.751244],
target: [2.3522, 48.8566],
passengers: 18000
}
];
const arcLayer = new ArcLayer({
id: 'routes',
data,
pickable: true,
getSourcePosition: d => d.source,
getTargetPosition: d => d.target,
getSourceColor: [0, 128, 255],
getTargetColor: [255, 80, 80],
getWidth: d => d.passengers,
widthScale: 0.0002,
widthMinPixels: 2,
transitions: {
getWidth: 1000
}
});
new Deck({
initialViewState: {
longitude: 20,
latitude: 52,
zoom: 3,
pitch: 45
},
controller: true,
layers: [arcLayer],
getTooltip: ({object}) =>
object && {
text: `Пассажиры: ${object.passengers}`
}
});
Данный пример демонстрирует большинство ключевых возможностей ArcLayer: построение дуг между городами, настройку цветов, управление толщиной линий, интерактивность, всплывающие подсказки и анимированное изменение визуальных параметров.