LineLayer — один из базовых слоёв библиотеки Deck.gl,
предназначенный для визуализации линейных объектов на карте или в
трёхмерной сцене. Слой отображает набор независимых отрезков, каждый из
которых задаётся начальной и конечной координатой.
Наиболее распространённые сценарии использования:
В отличие от PathLayer, который строит непрерывные
маршруты из множества точек, LineLayer работает именно с
отдельными сегментами. Каждый объект данных соответствует одной
линии.
import {Deck} from '@deck.gl/core';
import {LineLayer} from '@deck.gl/layers';
Создание слоя:
const layer = new LineLayer({
id: 'line-layer',
data: [
{
source: [-74.006, 40.7128],
target: [-118.2437, 34.0522]
}
],
getSourcePosition: d => d.source,
getTargetPosition: d => d.target
});
Минимальный набор данных состоит из двух координат:
[
{
source: [37.6176, 55.7558],
target: [30.3351, 59.9343]
}
]
Здесь:
source — начало линии;target — конец линии.Каждый элемент массива представляет отдельный линейный сегмент.
Уникальный идентификатор слоя.
id: 'roads-layer'
Deck.gl использует идентификатор для управления жизненным циклом слоя.
Источник данных.
data: roads
В качестве значения могут выступать:
data: array
data: promise
data: url
data: iterable
Пример загрузки JSON:
data: '/data/routes.json'
Возвращает координаты начала линии.
getSourcePosition: d => d.source
Если структура данных отличается:
getSourcePosition: d => [
d.startLng,
d.startLat
]
Также допускается работа с высотой:
getSourcePosition: d => [
d.lng,
d.lat,
d.altitude
]
Возвращает координаты конца линии.
getTargetPosition: d => d.target
Пример:
getTargetPosition: d => [
d.endLng,
d.endLat
]
Определяет цвет линии.
Формат:
[r, g, b]
или
[r, g, b, a]
Пример:
getColor: [255, 0, 0]
Красная линия.
С использованием альфа-канала:
getColor: [255, 0, 0, 128]
Полупрозрачная линия.
Цвет может вычисляться на основе данных.
getColor: d => {
if (d.type === 'highway') {
return [255, 100, 0];
}
return [100, 100, 255];
}
По интенсивности потока:
getColor: d => [
Math.min(d.volume * 5, 255),
50,
200
]
Определяет ширину линии.
getWidth: 5
Или:
getWidth: d => d.width
Пример:
getWidth: d => d.passengers / 1000
Чем больше пассажиропоток, тем толще линия.
Единицы измерения толщины.
По умолчанию:
widthUnits: 'pixels'
Возможные значения:
'pixels'
'meters'
'common'
Толщина не зависит от масштаба карты.
widthUnits: 'pixels',
getWidth: 3
Линия всегда будет отображаться шириной 3 пикселя.
Толщина рассчитывается в метрах.
widthUnits: 'meters',
getWidth: 100
Полезно для географических объектов.
Масштабирует ширину всех линий.
widthScale: 10
Если:
getWidth: 2
то фактическая ширина станет:
2 × 10 = 20
Минимальная ширина на экране.
widthMinPixels: 1
Пример:
widthMinPixels: 3
Даже при сильном уменьшении карты линия останется различимой.
Максимальная ширина линии.
widthMaxPixels: 20
Это ограничивает чрезмерное увеличение толстых сегментов.
Полупрозрачные линии часто используются для отображения больших объёмов данных.
getColor: [0, 128, 255, 80]
или
getColor: d => [
0,
150,
255,
d.opacity
]
LineLayer поддерживает трёхмерные координаты.
Пример:
{
source: [37.6176, 55.7558, 0],
target: [30.3351, 59.9343, 10000]
}
Настройка:
getSourcePosition: d => d.source,
getTargetPosition: d => d.target
В результате линия будет подниматься над поверхностью карты.
Один из самых популярных сценариев применения слоя.
Структура данных:
[
{
from: [-0.1276, 51.5074],
to: [2.3522, 48.8566],
passengers: 120000
}
]
Создание слоя:
new LineLayer({
id: 'flights',
data: flights,
getSourcePosition: d => d.from,
getTargetPosition: d => d.to,
getWidth: d => d.passengers / 20000,
getColor: [255, 140, 0]
})
Толщина линии показывает интенсивность авиасообщения.
Данные:
[
{
source: [10, 20],
target: [30, 40],
strength: 0.8
}
]
Слой:
new LineLayer({
id: 'network',
data,
getSourcePosition: d => d.source,
getTargetPosition: d => d.target,
getWidth: d => d.strength * 10,
getColor: d => [
255,
0,
0,
d.strength * 255
]
})
Сильные связи отображаются более толстыми и насыщенными линиями.
Разрешает взаимодействие с объектами.
pickable: true
Без этого свойства события выбора работать не будут.
Срабатывает при наведении курсора.
onHover: info => {
console.log(info.object);
}
Пример отображения подсказки:
onHover: ({object, x, y}) => {
if (object) {
showTooltip(object, x, y);
}
}
Обработка клика.
onClick: info => {
console.log(info.object);
}
Пример:
onClick: ({object}) => {
openRouteDetails(object.id);
}
При изменении внешних параметров слой можно обновлять выборочно.
new LineLayer({
getColor: d => colorScale(d.value),
updateTriggers: {
getColor: [theme]
}
})
При изменении theme Deck.gl пересчитает только цвета
линий.
Для больших объёмов данных рекомендуется применять бинарный формат.
Пример набора в несколько миллионов линий может быть представлен через типизированные массивы:
Float32Array
Uint8Array
Такой подход снижает нагрузку на сборщик мусора JavaScript и ускоряет передачу данных в GPU.
Менее эффективно:
getColor: d => {
return calculateComplexColor(d);
}
Более эффективно:
const colors = precomputeColors(data);
getColor: (_, {index}) => colors[index];
Избыточные пересчёты:
layers = [
new LineLayer({...})
];
Оптимизированный вариант:
updateTriggers: {
getWidth: [scale]
}
| Возможность | LineLayer | PathLayer |
|---|---|---|
| Отдельные сегменты | Да | Нет |
| Маршруты из множества точек | Нет | Да |
| Простота вычислений | Высокая | Средняя |
| Большие наборы связей | Отлично | Ограниченно |
| Графовые структуры | Отлично | Неудобно |
Для независимых соединений между объектами предпочтителен
LineLayer. Для дорог, треков GPS и сложных маршрутов обычно
используется PathLayer.
import {Deck} from '@deck.gl/core';
import {LineLayer} from '@deck.gl/layers';
const routes = [
{
source: [37.6176, 55.7558],
target: [30.3351, 59.9343],
traffic: 50
},
{
source: [37.6176, 55.7558],
target: [27.5615, 53.9045],
traffic: 80
}
];
const lineLayer = new LineLayer({
id: 'routes',
data: routes,
pickable: true,
getSourcePosition: d => d.source,
getTargetPosition: d => d.target,
getWidth: d => d.traffic / 10,
widthMinPixels: 2,
getColor: d => [
Math.min(d.traffic * 3, 255),
100,
255
],
onClick: ({object}) => {
console.log(object);
}
});
new Deck({
initialViewState: {
longitude: 37.6176,
latitude: 55.7558,
zoom: 4
},
controller: true,
layers: [lineLayer]
});
LineLayer представляет собой высокопроизводительный
инструмент визуализации линейных связей, оптимизированный для работы с
большим количеством независимых сегментов. Благодаря поддержке
GPU-рендеринга, динамической стилизации, интерактивности и трёхмерных
координат слой эффективно используется для построения сетей, маршрутов,
потоков данных и любых геопространственных связей между объектами.