Line

Линейный слой (line layer) в Mapbox GL JS предназначен для отрисовки геометрий типа LineString и MultiLineString из GeoJSON-источников. Он используется для визуализации дорог, маршрутов, границ, траекторий движения, сетей коммуникаций и любых непрерывных пространственных объектов.

Линейный слой относится к векторным слоям и полностью управляется стилями, выражениями и источниками данных Mapbox. Он может динамически изменяться в зависимости от масштаба, атрибутов данных и пользовательских взаимодействий.


Источник данных для line-слоя

Основой линейного слоя является GeoJSON-источник. Тип геометрии должен быть строго:

  • LineString
  • MultiLineString

Пример источника:

map.on('load', () => {
  map.addSource('route', {
    type: 'geojson',
    data: {
      type: 'Feature',
      geometry: {
        type: 'LineString',
        coordinates: [
          [71.4304, 51.1284],
          [71.4491, 51.1694],
          [71.4700, 51.1900]
        ]
      }
    }
  });
});

GeoJSON может быть:

  • статическим объектом
  • URL-источником
  • динамически обновляемым набором данных

Создание line layer

После добавления источника создаётся слой типа line:

map.addLayer({
  id: 'route-line',
  type: 'line',
  source: 'route',
  layout: {
    'line-join': 'round',
    'line-cap': 'round'
  },
  paint: {
    'line-color': '#3b82f6',
    'line-width': 4,
    'line-opacity': 0.9
  }
});

Ключевые параметры:

  • type: 'line' — определяет тип слоя
  • source — ссылка на GeoJSON источник
  • layout — геометрическое поведение линии
  • paint — визуальное оформление

Свойства layout для линий

line-join

Определяет способ соединения сегментов линии:

  • round — плавные скругления
  • bevel — срезанные углы
  • miter — острые углы
'line-join': 'round'

line-cap

Определяет форму концов линии:

  • butt — обрезанные
  • round — округлые
  • square — квадратные выступы
'line-cap': 'round'

Основные paint-свойства

line-color

Цвет линии может быть фиксированным или выражением:

'line-color': '#10b981'

Динамическая стилизация:

'line-color': [
  'interpolate',
  ['linear'],
  ['zoom'],
  5, '#60a5fa',
  10, '#3b82f6',
  15, '#1d4ed8'
]

line-width

Толщина линии в пикселях:

'line-width': 5

Зависимость от масштаба:

'line-width': [
  'interpolate',
  ['exponential', 1.2],
  ['zoom'],
  5, 2,
  10, 4,
  15, 10
]

line-opacity

Прозрачность слоя:

'line-opacity': 0.8

line-blur

Размытие линии для эффектов свечения:

'line-blur': 1.5

Используется для:

  • glow-эффектов
  • имитации тумана
  • визуализации потоков

line-offset

Сдвиг линии относительно исходной геометрии:

'line-offset': 2

Применяется для:

  • параллельных дорог
  • двойных контуров
  • визуального разделения потоков

Пунктирные линии: line-dasharray

Свойство line-dasharray позволяет создавать пунктирные линии:

'line-dasharray': [2, 4]

Где:

  • 2 — длина штриха
  • 4 — длина пробела

Более сложный вариант:

'line-dasharray': [0, 2, 3]

Градиент вдоль линии: line-gradient

Один из наиболее мощных инструментов — создание градиента, который изменяется вдоль геометрии.

map.addLayer({
  id: 'route-gradient',
  type: 'line',
  source: 'route',
  paint: {
    'line-width': 6,
    'line-gradient': [
      'interpolate',
      ['linear'],
      ['line-progress'],
      0, '#22c55e',
      0.5, '#eab308',
      1, '#ef4444'
    ]
  }
});

line-progress доступен только при использовании lineMetrics: true:

map.addSource('route', {
  type: 'geojson',
  lineMetrics: true,
  data: routeData
});

Анимация линии через dasharray

Анимация пунктирной линии достигается изменением line-dasharray:

let dashOffset = 0;

function animate() {
  dashOffset = (dashOffset + 0.2) % 4;

  map.setPaintProperty('route-line', 'line-dasharray', [
    0, dashOffset, 1.5, dashOffset
  ]);

  requestAnimationFrame(animate);
}

animate();

Используется для:

  • маршрутов движения
  • визуализации потоков данных
  • эффекта “движущейся дороги”

Мультилинии и сложные геометрии

MultiLineString позволяет объединять несколько линий:

geometry: {
  type: 'MultiLineString',
  coordinates: [
    [
      [71.1, 51.1],
      [71.2, 51.2]
    ],
    [
      [71.3, 51.3],
      [71.4, 51.4]
    ]
  ]
}

Каждая линия обрабатывается единым стилем слоя.


Данные и обновление линии

Обновление данных без пересоздания слоя:

const source = map.getSource('route');

source.setData({
  type: 'Feature',
  geometry: {
    type: 'LineString',
    coordinates: [
      [71.43, 51.12],
      [71.50, 51.20]
    ]
  }
});

Используется для:

  • трекинга объектов
  • обновления маршрутов
  • потоковой визуализации

Data-driven styling для линий

Line layer поддерживает выражения на основе свойств GeoJSON:

'line-color': [
  'match',
  ['get', 'type'],
  'highway', '#ef4444',
  'street', '#3b82f6',
  'path', '#22c55e',
  '#999999'
]

Иерархия и порядок слоёв

Порядок добавления критически влияет на визуализацию:

map.addLayer(backgroundLayer);
map.addLayer(routeLineLayer);
map.addLayer(highlightLineLayer);

Линии, добавленные позже:

  • отображаются выше
  • перекрывают предыдущие слои

Сложные визуальные эффекты

Контурная линия (casing effect)

Создаётся двумя слоями:

map.addLayer({
  id: 'route-casing',
  type: 'line',
  source: 'route',
  paint: {
    'line-color': '#111827',
    'line-width': 10
  }
});

map.addLayer({
  id: 'route-inner',
  type: 'line',
  source: 'route',
  paint: {
    'line-color': '#3b82f6',
    'line-width': 6
  }
});

Свечение линии

'line-blur': 3,
'line-color': '#60a5fa',
'line-width': 8,
'line-opacity': 0.6

Эффект усиливается при наложении нескольких слоёв с разной прозрачностью.


Производительность line-слоёв

При работе с большим количеством линий важны оптимизации:

  • использование упрощённых геометрий (simplify)
  • уменьшение количества вершин
  • кластеризация маршрутов при необходимости
  • минимизация пересчётов setData

Особенно критично при:

  • тысячах маршрутов
  • real-time трекинге
  • анимированных линиях

Использование выражений zoom-dependent

Линии часто адаптируются к масштабу:

'line-width': [
  'interpolate',
  ['linear'],
  ['zoom'],
  3, 1,
  10, 3,
  18, 12
]

Это позволяет:

  • скрывать детали на малых масштабах
  • усиливать визуализацию при приближении

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

Линии могут быть кликабельными:

map.on('click', 'route-line', (e) => {
  const feature = e.features[0];
  console.log(feature.properties);
});

Hover-эффект:

map.on('mouseenter', 'route-line', () => {
  map.getCanvas().style.cursor = 'pointer';
});

Комбинирование line с другими слоями

Line-слои часто используются вместе с:

  • circle (узлы маршрута)
  • symbol (подписи)
  • fill (зоны)

Типичный паттерн:

  • линия маршрута
  • точки остановок
  • подписи объектов

Сложные маршруты и сегментация

Разбиение линии на сегменты позволяет:

  • окрашивать участки по состоянию
  • отображать прогресс
  • визуализировать статус

Пример:

'line-color': [
  'case',
  ['==', ['get', 'status'], 'active'], '#22c55e',
  ['==', ['get', 'status'], 'inactive'], '#ef4444',
  '#9ca3af'
]