Переключение между типами карт

В Google Maps JavaScript API базовая визуализация карты опирается на параметр mapTypeId, который определяет способ отображения географических данных. Система поддерживает несколько встроенных типов карт, а также позволяет создавать пользовательские реализации через интерфейс MapType.

Ключевые предустановленные значения:

  • roadmap — стандартная схема дорог
  • satellite — спутниковые снимки
  • hybrid — спутник с наложенными подписями и дорогами
  • terrain — рельефная карта

Каждый тип карты представляет собой отдельный слой визуализации, переключение между которыми осуществляется без пересоздания объекта карты.


Базовая инициализация с поддержкой типов карт

При создании экземпляра карты тип задаётся через свойство mapTypeId:

const map = new google.maps.Map(document.getElementById("map"), {
  center: { lat: 55.751244, lng: 37.618423 },
  zoom: 10,
  mapTypeId: "roadmap"
});

Дополнительно можно указать доступные типы в интерфейсе управления:

const map = new google.maps.Map(document.getElementById("map"), {
  center: { lat: 55.751244, lng: 37.618423 },
  zoom: 10,
  mapTypeControl: true,
  mapTypeControlOptions: {
    mapTypeIds: ["roadmap", "satellite", "hybrid", "terrain"]
  }
});

mapTypeControl включает стандартный переключатель в интерфейсе карты, а mapTypeControlOptions.mapTypeIds определяет набор доступных вариантов.


Программное переключение типа карты

Основной метод изменения визуального режима — setMapTypeId():

map.setMapTypeId("satellite");

Метод применяется динамически и не требует пересоздания карты. Состояние карты обновляется мгновенно, включая перерисовку тайлов и слоёв.

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

const currentType = map.getMapTypeId();

Реализация пользовательского переключателя

Часто требуется замена стандартного UI на кастомный элемент управления. В этом случае используется прямое управление через DOM и API карты.

const buttons = document.querySelectorAll(".map-type-btn");

buttons.forEach(btn => {
  btn.addEventListener("click", () => {
    map.setMapTypeId(btn.dataset.type);
  });
});

HTML-структура:

<button class="map-type-btn" data-type="roadmap">Схема</button>
<button class="map-type-btn" data-type="satellite">Спутник</button>
<button class="map-type-btn" data-type="terrain">Рельеф</button>

Такой подход позволяет полностью контролировать интерфейс переключения и интегрировать его в дизайн приложения.


Работа с MapTypeControl и встроенным UI

Стандартный элемент управления можно кастомизировать:

const map = new google.maps.Map(document.getElementById("map"), {
  mapTypeControl: true,
  mapTypeControlOptions: {
    style: google.maps.MapTypeControlStyle.DROPDOWN_MENU,
    position: google.maps.ControlPosition.TOP_RIGHT,
    mapTypeIds: ["roadmap", "satellite", "terrain"]
  }
});

Доступные стили:

  • DEFAULT — стандартный переключатель
  • DROPDOWN_MENU — выпадающий список
  • HORIZONTAL_BAR — горизонтальная панель кнопок

Расположение контролов задаётся через ControlPosition.


Событие изменения типа карты

Для отслеживания переключения используется событие maptypeid_changed:

map.addListener("maptypeid_changed", () => {
  const type = map.getMapTypeId();
  console.log("Текущий тип карты:", type);
});

Событие полезно для синхронизации состояния интерфейса, сохранения настроек пользователя и аналитики.


Сохранение выбранного типа карты

Часто применяется сохранение состояния через localStorage:

map.addListener("maptypeid_changed", () => {
  localStorage.setItem("mapType", map.getMapTypeId());
});

Восстановление при загрузке:

const savedType = localStorage.getItem("mapType");

const map = new google.maps.Map(document.getElementById("map"), {
  center: { lat: 55.751244, lng: 37.618423 },
  zoom: 10,
  mapTypeId: savedType || "roadmap"
});

Такой подход обеспечивает устойчивость интерфейса между сессиями.


Ограничение доступных типов карты

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

map.setOptions({
  mapTypeControlOptions: {
    mapTypeIds: ["roadmap", "satellite"]
  }
});

Удаление типов из списка автоматически скрывает их из интерфейса и блокирует переключение.


Пользовательские типы карт

API позволяет создавать собственные типы через реализацию интерфейса MapType. Такой механизм используется для кастомных тайлов, нестандартных слоёв или экспериментальных визуализаций.

Базовая структура:

function CustomMapType(tileSize) {
  this.tileSize = tileSize;
  this.maxZoom = 18;
  this.name = "Custom";
}

CustomMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
  const img = ownerDocument.createElement("img");
  img.src = `https://example.com/tiles/${zoom}/${coord.x}/${coord.y}.png`;
  img.style.width = this.tileSize.width + "px";
  img.style.height = this.tileSize.height + "px";
  return img;
};

CustomMapType.prototype.releaseTile = function(tile) {
  tile = null;
};

Регистрация типа:

const customMapType = new CustomMapType(new google.maps.Size(256, 256));

map.mapTypes.set("custom_map", customMapType);
map.setMapTypeId("custom_map");

Управление набором mapTypes

Коллекция map.mapTypes представляет собой реестр доступных типов карт.

Добавление:

map.mapTypes.set("terrain", google.maps.MapTypeId.TERRAIN);

Удаление:

map.mapTypes.remove("terrain");

Проверка наличия:

const exists = map.mapTypes.has("satellite");

Стилизация карт и влияние на типы

Хотя стилизация через styles не создаёт новый тип карты, она часто используется совместно с переключением mapTypeId.

const styledMapType = new google.maps.StyledMapType([
  { elementType: "geometry", stylers: [{ color: "#242f3e" }] },
  { elementType: "labels.text.stroke", stylers: [{ color: "#242f3e" }] },
  { elementType: "labels.text.fill", stylers: [{ color: "#746855" }] }
]);

map.mapTypes.set("styled", styledMapType);

map.setMapTypeId("styled");

Таким образом формируется гибрид между стандартными типами и визуальными темами.


Динамическое переключение на основе масштаба

В интерфейсах с адаптивной логикой тип карты часто меняется в зависимости от zoom:

map.addListener("zoom_changed", () => {
  const zoom = map.getZoom();

  if (zoom < 8) {
    map.setMapTypeId("terrain");
  } else {
    map.setMapTypeId("roadmap");
  }
});

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


Интеграция с внешними контролами состояния приложения

При построении сложных интерфейсов состояние типа карты синхронизируется с внешними хранилищами состояния (Redux-подобные архитектуры, event bus, URL state).

Пример синхронизации через URL:

function updateUrl(type) {
  const url = new URL(window.location);
  url.searchParams.set("mapType", type);
  window.history.replaceState({}, "", url);
}

map.addListener("maptypeid_changed", () => {
  updateUrl(map.getMapTypeId());
});

Чтение состояния:

const params = new URLSearchParams(window.location.search);
const type = params.get("mapType") || "roadmap";

Особенности поведения при переключении

При смене типа карты сохраняются:

  • центр карты
  • уровень масштабирования
  • маркеры и оверлеи
  • пользовательские слои

Перерисовка затрагивает только тайловую подложку и связанные визуальные слои базовой карты.