Метод setStyle

Метод setStyle в библиотеке Mapbox GL JS используется для полной замены текущего стиля карты на новый. Он работает на уровне всего рендера и затрагивает все источники данных, слои, фильтры, изображения и конфигурацию отображения. Это один из наиболее «тяжёлых» методов API, поскольку инициирует пересборку визуального состояния карты.


Общая сигнатура

map.setStyle(style, options);

Параметры

style Строка или объект, описывающий стиль карты:

  • URL на стиль Mapbox
  • JSON-объект стиля Mapbox Style Specification

options (необязательный параметр) Объект с настройками поведения при смене стиля.

Пример:

map.setStyle('mapbox://styles/mapbox/streets-v12');

Поведение метода

При вызове setStyle происходит полная перезагрузка стиля карты:

  • удаляются все текущие слои (layers)
  • очищаются источники данных (sources)
  • сбрасываются изображения (images)
  • пересоздаётся стиль рендеринга WebGL
  • загружается новый стиль
  • повторно применяются базовые параметры карты

Важно учитывать, что сам объект map не уничтожается — пересоздаётся только визуальная часть.


Внутренний жизненный цикл смены стиля

Процесс смены можно условно разделить на этапы:

1. Инициализация смены

При вызове setStyle карта помечается как находящаяся в состоянии загрузки нового стиля.

map.setStyle(newStyle);

На этом этапе:

  • текущий стиль «замораживается»
  • активируется событие styledata
  • сбрасываются временные состояния слоёв

2. Очистка текущего состояния

Удаляются:

  • пользовательские слои, добавленные через addLayer
  • источники данных (addSource)
  • загруженные изображения (addImage)
  • кастомные шейдерные состояния

Это означает, что любые динамически добавленные элементы исчезают.


3. Загрузка нового стиля

Если передан URL:

map.setStyle('mapbox://styles/mapbox/light-v11');

Mapbox GL JS выполняет:

  • HTTP-запрос к стилю
  • загрузку JSON-описания
  • валидацию структуры по спецификации Mapbox Style

Если передан объект:

map.setStyle({
  version: 8,
  sources: {},
  layers: []
});

Загрузка происходит синхронно без сетевого запроса.


4. Пересборка источников и слоёв

После загрузки нового стиля:

  • создаются новые source
  • инициализируются layer
  • пересчитываются зависимости между слоями
  • формируется порядок отрисовки

5. Финальная отрисовка

После завершения загрузки вызываются события:

  • style.load
  • render
  • idle

Карта становится готовой к использованию.


Поведение источников данных

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

Пример:

map.addSource('points', {
  type: 'geojson',
  data: 'data.geojson'
});

После вызова:

map.setStyle('mapbox://styles/mapbox/dark-v11');

источник points будет удалён.

Важный момент

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

map.on('style.load', () => {
  map.addSource('points', {
    type: 'geojson',
    data: 'data.geojson'
  });
});

Работа с пользовательскими слоями

Все добавленные слои также удаляются.

map.addLayer({
  id: 'custom-layer',
  type: 'circle',
  source: 'points'
});

После смены стиля:

map.setStyle(newStyle);

слой custom-layer перестаёт существовать.

Восстановление слоёв

Обычно используется событие:

map.on('style.load', () => {
  map.addLayer({
    id: 'custom-layer',
    type: 'circle',
    source: 'points'
  });
});

События, связанные с setStyle

style.load

Срабатывает после полной загрузки нового стиля.

map.on('style.load', () => {
  // стиль полностью загружен
});

styledata

Вызывается при частичной загрузке данных стиля.

Используется для отслеживания прогресса:

map.on('styledata', () => {
  console.log('данные стиля обновляются');
});

data

Генерируется при обновлении источников и тайлов.


Влияние на состояние карты

При вызове setStyle сбрасываются:

  • текущие фильтры слоёв
  • выражения (expressions)
  • состояния видимости слоёв
  • порядок слоёв
  • кастомные изображения

Однако сохраняются:

  • координаты центра карты
  • уровень масштабирования
  • угол наклона (pitch)
  • вращение (bearing)

Опции метода setStyle

Mapbox GL JS позволяет передавать дополнительные параметры:

map.setStyle('mapbox://styles/mapbox/outdoors-v12', {
  diff: false
});

diff

diff: true/false

Определяет, будет ли применяться «дифференциальное» обновление стиля.

  • true — пытается сохранить существующие слои и источники, если они совпадают
  • false — полная перезагрузка стиля

Практика использования diff

Полная замена (по умолчанию)

map.setStyle('mapbox://styles/mapbox/light-v11');

Используется при смене типа карты (например, с улиц на спутник).


Частичное обновление

map.setStyle('mapbox://styles/mapbox/streets-v12', {
  diff: true
});

Позволяет сохранить часть состояния, если структура стиля совместима.


Ограничения метода setStyle

1. Потеря динамических данных

Все добавленные через API объекты удаляются.


2. Асинхронная природа

Нельзя сразу обращаться к слоям после вызова:

map.setStyle(newStyle);

// ❌ слой ещё не существует
map.getLayer('roads');

Правильный подход:

map.once('style.load', () => {
  map.getLayer('roads');
});

3. Нагрузка на производительность

Каждый вызов:

  • пересоздаёт WebGL контекст
  • перезагружает тайлы
  • заново строит дерево слоёв

Частые вызовы setStyle приводят к заметным лагам.


Взаимодействие с пользовательским состоянием

Часто требуется сохранять:

  • выбранные объекты
  • активные фильтры
  • пользовательские слои

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

const state = {
  filters: map.getFilter('my-layer'),
  center: map.getCenter(),
  zoom: map.getZoom()
};

map.setStyle(newStyle);

map.once('style.load', () => {
  map.setFilter('my-layer', state.filters);
  map.setCenter(state.center);
  map.setZoom(state.zoom);
});

Пример комплексного использования

map.setStyle('mapbox://styles/mapbox/dark-v11');

map.once('style.load', () => {
  map.addSource('cities', {
    type: 'geojson',
    data: '/cities.geojson'
  });

  map.addLayer({
    id: 'cities-layer',
    type: 'circle',
    source: 'cities',
    paint: {
      'circle-radius': 6,
      'circle-color': '#ff0000'
    }
  });
});

Влияние на кеширование

Mapbox GL JS активно использует кеш:

  • тайлы не всегда загружаются повторно
  • стили кешируются браузером
  • изображения повторно используются при совпадении URL

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


Связь с архитектурой Mapbox GL JS

Метод setStyle является точкой пересборки всей графической сцены:

  • Style Manager уничтожает старую структуру
  • Tile Manager пересоздаёт источники
  • Renderer заново строит WebGL pipeline

Фактически это аналог «перезапуска сцены» без пересоздания карты как объекта.


Частые ошибки при использовании

Обращение к слоям до загрузки

map.setStyle(style);
map.getLayer('layer'); // ошибка

Потеря источников

map.setStyle(style);
// addSource не выполнен заново

Частые вызовы setStyle

setInterval(() => {
  map.setStyle(nextStyle);
}, 1000);

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


Рекомендованные паттерны

Централизованное управление стилем

function changeStyle(style) {
  map.setStyle(style);

  map.once('style.load', initLayers);
}

Сохранение состояния

function saveState(map) {
  return {
    center: map.getCenter(),
    zoom: map.getZoom(),
    bearing: map.getBearing(),
    pitch: map.getPitch()
  };
}

Восстановление состояния

function restoreState(map, state) {
  map.setCenter(state.center);
  map.setZoom(state.zoom);
  map.setBearing(state.bearing);
  map.setPitch(state.pitch);
}