Стилизация маршрута

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

В Mapbox GL JS стилизация маршрутов осуществляется через слои типа line. Внешний вид линии определяется набором свойств, задаваемых в объекте paint и частично в объекте layout.

Маршрут обычно хранится в формате GeoJSON и отображается как объект LineString.

map.addSource('route', {
    type: 'geojson',
    data: {
        type: 'Feature',
        geometry: {
            type: 'LineString',
            coordinates: [
                [37.6176, 55.7558],
                [37.6300, 55.7600],
                [37.6500, 55.7700]
            ]
        }
    }
});

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

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

Результатом становится базовая линия маршрута синего цвета толщиной 6 пикселей.


Основные параметры оформления линии

Цвет маршрута

Свойство line-color задаёт основной цвет.

paint: {
    'line-color': '#ff0000'
}

Пример с использованием RGB:

paint: {
    'line-color': 'rgb(0, 150, 255)'
}

Пример с использованием прозрачности через RGBA:

paint: {
    'line-color': 'rgba(0, 150, 255, 0.5)'
}

Толщина линии

Толщина задаётся свойством line-width.

paint: {
    'line-width': 8
}

Увеличение толщины делает маршрут заметнее на фоне дорог и других объектов карты.


Прозрачность

Для настройки прозрачности используется line-opacity.

paint: {
    'line-color': '#007cbf',
    'line-opacity': 0.5
}

Значение изменяется от:

  • 0 — полностью прозрачная линия;
  • 1 — полностью непрозрачная линия.

Скругление углов маршрута

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

Свойство line-join управляет соединением сегментов.

layout: {
    'line-join': 'round'
}

Доступные варианты:

Значение Описание
round скруглённые соединения
bevel срезанные углы
miter острые углы

Наиболее распространён вариант:

layout: {
    'line-join': 'round'
}

Скругление концов линии

Свойство line-cap отвечает за внешний вид начала и конца маршрута.

layout: {
    'line-cap': 'round'
}

Возможные значения:

Значение Описание
butt плоский край
round округлый край
square квадратный край

Для навигационных маршрутов обычно используется:

layout: {
    'line-cap': 'round'
}

Создание контуров маршрута

Популярный приём — отображение линии с обводкой.

Для этого создаются два слоя:

  1. Нижний слой-контур.
  2. Верхний основной маршрут.

Контур

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

Основной маршрут

map.addLayer({
    id: 'route-main',
    type: 'line',
    source: 'route',
    paint: {
        'line-color': '#1976d2',
        'line-width': 6
    }
});

Такой подход визуально отделяет маршрут от фона карты.


Создание пунктирного маршрута

Для отображения предполагаемого пути или альтернативного маршрута применяется пунктир.

Используется свойство line-dasharray.

paint: {
    'line-color': '#ff9800',
    'line-width': 5,
    'line-dasharray': [2, 2]
}

Расшифровка массива:

[длина штриха, длина промежутка]

Примеры:

line-dasharray: [1, 1]
line-dasharray: [3, 2]
line-dasharray: [5, 1]

Многоцветные маршруты

Mapbox GL JS позволяет изменять цвет вдоль маршрута.

Например, разные участки пути могут обозначать:

  • скорость движения;
  • тип дороги;
  • степень загруженности;
  • качество покрытия.

Для этого используется свойство line-gradient.

Необходима установка параметра:

lineMetrics: true

при создании источника.

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

Далее задаётся градиент.

paint: {
    'line-width': 8,
    'line-gradient': [
        'interpolate',
        ['linear'],
        ['line-progress'],
        0,
        '#00ff00',
        0.5,
        '#ffff00',
        1,
        '#ff0000'
    ]
}

В результате маршрут плавно меняет цвет:

  • зелёный;
  • жёлтый;
  • красный.

Градиент по длине маршрута

Часто используется эффект постепенного изменения цвета от начала до конца пути.

paint: {
    'line-width': 8,
    'line-gradient': [
        'interpolate',
        ['linear'],
        ['line-progress'],
        0,
        '#2196f3',
        1,
        '#9c27b0'
    ]
}

Такой стиль часто применяется в трекинговых системах и визуализации перемещений.


Масштабируемая толщина маршрута

Линия может автоматически менять толщину при изменении масштаба карты.

paint: {
    'line-width': [
        'interpolate',
        ['linear'],
        ['zoom'],
        5, 2,
        10, 5,
        15, 12
    ]
}

Логика:

Масштаб Толщина
5 2 px
10 5 px
15 12 px

Маршрут остаётся удобочитаемым на любом уровне приближения.


Изменение цвета в зависимости от масштаба

Аналогично можно изменять цвет.

paint: {
    'line-color': [
        'interpolate',
        ['linear'],
        ['zoom'],
        5, '#4caf50',
        10, '#2196f3',
        15, '#f44336'
    ]
}

На разных уровнях детализации пользователь будет видеть различные варианты оформления.


Использование данных маршрута для стилизации

Если GeoJSON содержит свойства, внешний вид линии можно изменять динамически.

Пример данных:

{
    type: "Feature",
    properties: {
        status: "active"
    },
    geometry: {
        type: "LineString",
        coordinates: [...]
    }
}

Стилизация:

paint: {
    'line-color': [
        'match',
        ['get', 'status'],
        'active', '#4caf50',
        'paused', '#ff9800',
        'finished', '#9e9e9e',
        '#000000'
    ]
}

Теперь цвет определяется значением свойства status.


Отображение нескольких маршрутов

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

GeoJSON:

{
    type: "FeatureCollection",
    features: [
        {
            type: "Feature",
            properties: {
                type: "main"
            },
            geometry: {...}
        },
        {
            type: "Feature",
            properties: {
                type: "alternative"
            },
            geometry: {...}
        }
    ]
}

Стилизация:

paint: {
    'line-color': [
        'match',
        ['get', 'type'],
        'main', '#1976d2',
        'alternative', '#9e9e9e',
        '#000000'
    ],
    'line-width': [
        'match',
        ['get', 'type'],
        'main', 8,
        'alternative', 4,
        2
    ]
}

Главный маршрут становится визуально доминирующим.


Подсветка маршрута при наведении

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

Создаётся состояние объекта:

map.on('mousemove', 'route-line', (e) => {
    map.setFeatureState(
        {
            source: 'routes',
            id: e.features[0].id
        },
        {
            hover: true
        }
    );
});

Далее используется выражение:

paint: {
    'line-color': [
        'case',
        ['boolean', ['feature-state', 'hover'], false],
        '#ff0000',
        '#1976d2'
    ]
}

При наведении маршрут автоматически меняет цвет.


Анимационная подсветка маршрута

Эффект движения по маршруту можно реализовать через циклическое изменение параметров слоя.

Пример изменения прозрачности:

let opacity = 1;

setInterval(() => {
    opacity = opacity === 1 ? 0.3 : 1;

    map.setPaintProperty(
        'route-line',
        'line-opacity',
        opacity
    );
}, 500);

Маршрут начинает пульсировать.


Отображение пройденной и оставшейся части маршрута

В навигационных приложениях часто требуется разделять:

  • уже пройденный участок;
  • оставшийся путь.

Обычно используются два отдельных источника данных:

passedRoute
remainingRoute

Для каждого создаётся свой слой.

Пройденная часть:

paint: {
    'line-color': '#4caf50',
    'line-width': 8
}

Оставшаяся часть:

paint: {
    'line-color': '#2196f3',
    'line-width': 8
}

По мере движения координаты обновляются, и визуализация показывает текущее положение на маршруте.


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

Вместо сплошного цвета возможно применение изображений.

Сначала изображение загружается:

map.loadImage('arrow.png', (error, image) => {
    if (error) throw error;

    map.addImage('arrow-pattern', image);
});

После этого применяется шаблон:

paint: {
    'line-pattern': 'arrow-pattern'
}

Текстурированные маршруты используются для:

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

Комбинирование нескольких эффектов

Наиболее качественные маршруты обычно объединяют несколько техник одновременно.

Пример профессионального оформления:

map.addLayer({
    id: 'route',
    type: 'line',
    source: 'route',
    layout: {
        'line-cap': 'round',
        'line-join': 'round'
    },
    paint: {
        'line-color': '#1976d2',
        'line-width': [
            'interpolate',
            ['linear'],
            ['zoom'],
            5, 3,
            15, 10
        ],
        'line-opacity': 0.9
    }
});

В таком варианте маршрут обладает следующими характеристиками:

  • плавные соединения сегментов;
  • округлённые окончания;
  • адаптивная толщина;
  • высокая контрастность;
  • хорошая читаемость на различных масштабах;
  • совместимость с интерактивными эффектами и динамическим обновлением данных.

Комплексная стилизация маршрута является одним из ключевых инструментов визуальной коммуникации в Mapbox GL JS. Благодаря комбинации цветов, градиентов, контуров, пунктирных линий, шаблонов, анимации и выражений стилей можно создавать навигационные интерфейсы любой сложности — от простых трекеров перемещения до полноценных геоинформационных и транспортных систем.