Skip to main content
Стилизация карты под бренд: тёмный режим, цвета и без водяных знаков
Tutorials

Стилизация карты под бренд: тёмный режим, цвета и без водяных знаков

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

Brent van der Heiden9 min read
#custom map style#dark mode map#branded map#maps api#map customization#mapbox style

Почти все карты, которые вы видели в приложениях конкурентов, используют один и тот же стиль по умолчанию. Стандартные бежевые дороги, вода приглушённого сине-зелёного оттенка, перегруженные значки POI, которые спорят за внимание с вашим интерфейсом. Это универсальные настройки по умолчанию, сделанные так, чтобы никого не раздражать и никого не радовать. Они ясно сообщают одно: продукт использует картографическую библиотеку, но не управляет тем, как выглядит его карта.

Собственная стилизация карты это меняет. Тёмная карта на логистической панели, дорожная сеть в фирменном зелёном цвете в приложении недвижимости, чистый минималистичный стиль с вашим логотипом на месте водяного знака атрибуции: именно такие детали превращают инструмент в продукт.

В этом туториале разбирается спецификация стилей Mapbox в реализации MapAtlas, от структуры Style JSON до готового переключателя светлой и тёмной темы на React. Опыт работы с ГИС не нужен. Достаточно уверенно работать с JSON и JavaScript.

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

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

Стиль по умолчанию у тайлового провайдера рассчитан на то, чтобы карта читалась для максимально широкой аудитории в максимально разных сценариях. Информационная насыщенность в нём важнее эстетики. Дороги должны быть видны. Подписи должны контрастировать с фоном. Значки POI должны узнаваться.

Ни одна из этих целей не совпадает с целями вашего продукта. Скорее всего, приложению важна лишь небольшая часть того, что есть на карте (маршруты доставки, объекты недвижимости, медицинские учреждения), а всё остальное становится визуальным шумом.

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

Как устроена спецификация стилей

Стиль MapAtlas представляет собой JSON-документ с пятью ключевыми разделами:

{
  "version": 8,
  "name": "My Brand Style",
  "sources": { ... },
  "glyphs": "https://cdn.mapmetrics-atlas.net/basemaps-assets/fonts/{fontstack}/{range}.pbf",
  "sprite": "https://cdn.mapmetrics-atlas.net/basemaps-assets/sprites/v4/light",
  "layers": [ ... ]
}
  • sources: откуда берутся данные карты (эндпоинты векторных тайлов MapAtlas)
  • glyphs: откуда загружать файлы шрифтов для отрисовки подписей
  • sprite: откуда загружать изображения значков для маркеров POI
  • layers: упорядоченный список визуальных слоёв, у каждого из которых есть свойства отрисовки (paint) и компоновки (layout)

Больше всего времени вы будете проводить в массиве layers. Каждый слой задаёт тип отображения (fill, line, symbol, circle, fill-extrusion), объекты источника, которые нужно рисовать, и способ их отрисовки.

Вот минимальный, но полный стиль, который отрисовывает векторную подложку:

{
  "version": 8,
  "name": "Brand Base",
  "sources": {
    "mapatlas": {
      "type": "vector",
      "tiles": ["https://gateway.mapmetrics-atlas.net/planet20251013/{z}/{x}/{y}.mvt?token=YOUR_API_KEY"],
      "minzoom": 0,
      "maxzoom": 14
    }
  },
  "glyphs": "https://cdn.mapmetrics-atlas.net/basemaps-assets/fonts/{fontstack}/{range}.pbf",
  "sprite": "https://cdn.mapmetrics-atlas.net/basemaps-assets/sprites/v4/light",
  "layers": [
    {
      "id": "background",
      "type": "background",
      "paint": { "background-color": "#f5f0eb" }
    }
  ]
}

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

Тёмная тема: меняем основные цвета

Тёмная карта не является просто инвертированным растровым изображением. Это совершенно другой набор свойств отрисовки, применённый к той же векторной геометрии. Это одна из главных причин существования векторных тайлов: один тайл, бесконечно много визуальных вариантов.

Ключевые цвета, которые нужно поменять для тёмной темы:

СлойСветлая темаТёмная тема
Фон (суша)#f5f0eb#1a1a2e
Вода#a8d5e5#0d3b66
Городская застройка#e8e0d5#16213e
Парки и зелёные зоны#c8e6c9#1b4332
Дороги (крупные)#ffffff#3a3a5c
Дороги (второстепенные)#efefef#2d2d4a
Подписи дорог#333333#cccccc

Вот как это применяется в слое стиля:

{
  "id": "water",
  "type": "fill",
  "source": "mapatlas",
  "source-layer": "water",
  "paint": {
    "fill-color": "#0d3b66",
    "fill-opacity": 1
  }
}
{
  "id": "road-major",
  "type": "line",
  "source": "mapatlas",
  "source-layer": "transportation",
  "filter": ["==", "class", "primary"],
  "layout": {
    "line-join": "round",
    "line-cap": "round"
  },
  "paint": {
    "line-color": "#3a3a5c",
    "line-width": ["interpolate", ["linear"], ["zoom"], 10, 1, 16, 4]
  }
}

Выражение interpolate в line-width масштабирует ширину дороги в зависимости от уровня зума: узкая линия на мелком масштабе и более широкая при приближении. Это стилизация на основе данных без каких-либо дополнительных сетевых запросов.

Применяем фирменные цвета

Большинство дизайн-систем задают основной цвет (например, #97C70A), дополнительный цвет и нейтральную палитру. Карта должна использовать точно те же значения, а не похожие.

Фирменные цвета стоит применять к следующим слоям.

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

{
  "id": "road-highlighted",
  "type": "line",
  "source": "mapatlas",
  "source-layer": "transportation",
  "filter": ["==", "class", "primary"],
  "paint": {
    "line-color": "#97C70A",
    "line-width": 3,
    "line-opacity": 0.8
  }
}

Собственные маркеры POI. Замените стандартные значки своими: разместите собственный спрайт и обновите URL в sprite. Затем используйте свои значки в слоях типа symbol:

{
  "id": "brand-poi",
  "type": "symbol",
  "source": "mapatlas",
  "source-layer": "poi",
  "layout": {
    "icon-image": "brand-pin",
    "icon-size": 1.2,
    "text-field": ["get", "name"],
    "text-font": ["Inter Bold", "Noto Sans Regular"],
    "text-size": 12,
    "text-offset": [0, 1.5],
    "text-anchor": "top"
  },
  "paint": {
    "text-color": "#97C70A",
    "text-halo-color": "#1a1a2e",
    "text-halo-width": 1
  }
}

Собственные шрифты для подписей на карте

Стандартные шрифты подписей на карте безлики. Если ваш бренд использует Inter, Roboto или собственную гарнитуру, её можно применить и к подписям на карте.

MapAtlas отдаёт глифы со своего эндпоинта, который поддерживает стандартный формат глифов Mapbox. Чтобы использовать собственный шрифт:

  1. Сгенерируйте файлы глифов .pbf из своей гарнитуры с помощью инструмента вроде fontnik.
  2. Разместите файлы глифов на CDN или на своём сервере.
  3. Обновите поле glyphs в Style JSON:
{
  "glyphs": "https://your-cdn.com/fonts/{fontstack}/{range}.pbf"
}
  1. Укажите шрифт в свойстве text-font любого слоя типа symbol:
"text-font": ["Inter Bold", "Noto Sans Regular"]

Всегда указывайте резервный шрифт (Noto Sans покрывает символы Unicode, которых может не быть в основном шрифте). Для каждого символа рендерер берёт первый шрифт из массива, в котором есть нужный глиф.

Удаление водяных знаков и атрибуции

MapAtlas поддерживает полноценный white-label. Логотип MapAtlas можно полностью убрать с карты, сохранив указание OpenStreetMap, которого требует лицензия на данные.

В SDK атрибуция выводится элементом управления, который можно отключить:

const map = new mapmetricsgl.Map({
  container: 'map',
  style: 'https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_STYLE_ID/style.json&token=YOUR_API_KEY',
  center: [4.9041, 52.3676],
  zoom: 12,
  attributionControl: false,  // Убираем стандартный элемент атрибуции
});

Если атрибуцию нужно оставить, но оформить под ваш интерфейс, скройте стандартный элемент и добавьте свой:

map.addControl(
  new mapmetricsgl.AttributionControl({
    customAttribution: 'Map data © OpenStreetMap contributors',
    compact: true,
  }),
  'bottom-left'
);

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

Переключатель светлой и тёмной темы на React

Ниже полный React-компонент карты с переключателем светлой и тёмной темы, который через CSS-переменные синхронизирует тему с остальным интерфейсом:

import { useEffect, useRef, useState } from 'react';
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';

const STYLES = {
  light: 'https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_STYLE_ID/style.json&token=YOUR_API_KEY',
  dark:  'https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_DARK_STYLE_ID/style.json&token=YOUR_API_KEY',
};

export function BrandedMap({ center = [4.9041, 52.3676], zoom = 12 }) {
  const containerRef = useRef(null);
  const mapRef       = useRef(null);
  const [theme, setTheme] = useState('light');

  useEffect(() => {
    const map = new mapmetricsgl.Map({
      container:        containerRef.current,
      style:            STYLES.light,
      center,
      zoom,
      attributionControl: false,
    });

    map.addControl(
      new mapmetricsgl.AttributionControl({ compact: true }),
      'bottom-left'
    );

    mapRef.current = map;
    return () => map.remove();
  }, []);

  useEffect(() => {
    if (mapRef.current) {
      mapRef.current.setStyle(STYLES[theme]);
    }
  }, [theme]);

  return (
    <div style={{ position: 'relative' }}>
      <div ref={containerRef} style={{ width: '100%', height: '500px' }} />
      <button
        onClick={() => setTheme(t => t === 'light' ? 'dark' : 'light')}
        style={{
          position: 'absolute',
          top: 12,
          right: 12,
          padding: '8px 16px',
          background: theme === 'dark' ? '#ffffff' : '#1a1a2e',
          color:      theme === 'dark' ? '#1a1a2e' : '#ffffff',
          border: 'none',
          borderRadius: 6,
          cursor: 'pointer',
          zIndex: 1,
        }}
      >
        {theme === 'light' ? 'Тёмная тема' : 'Светлая тема'}
      </button>
    </div>
  );
}

Вызов setStyle перерисовывает карту в новой цветовой схеме. Данные тайлов, которые уже есть в кэше, повторно не загружаются: меняется только их визуальное представление.

Размещение собственного Style JSON

Для полного контроля разместите Style JSON как статический файл на своём CDN или в бакете S3. Это позволяет:

  • Хранить стиль в системе контроля версий вместе с кодом приложения.
  • Обновлять визуальный дизайн без повторного деплоя приложения (достаточно обновить размещённый JSON).
  • Использовать разные стили для разных окружений (preview и production).

Загрузка размещённого стиля во время работы приложения:

const map = new mapmetricsgl.Map({
  container: 'map',
  style: 'https://your-cdn.com/styles/brand-dark.json',
  center: [4.9041, 52.3676],
  zoom: 12,
});

Единственное ограничение связано с CORS: Style JSON нужно отдавать с заголовком Access-Control-Allow-Origin: * (или с вашим конкретным доменом), чтобы браузер мог загрузить его с другого источника.

Рабочий процесс разработки стиля

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

  1. Возьмите за основу базовый Style JSON от MapAtlas. Создайте стиль в разделе Styles портала MapMetrics, скопируйте его Style URL и скачайте JSON, запросив этот URL.
  2. Редактируйте JSON в своём редакторе и отслеживайте, какой слой влияет на какой визуальный элемент.
  3. Перезагрузите карту с изменённым Style JSON и оцените результат.
  4. Когда стиль стабилизируется, закоммитьте Style JSON в репозиторий и разместите его на CDN.

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

Если вы переходите с Mapbox и хотите понять, что изменилось, посмотрите сравнение возможностей и цен в статье Mapbox vs MapAtlas: какой maps API подходит для вашего проекта в ЕС.

А архитектурная основа, благодаря которой всё это возможно, подробно разобрана в статье Векторные тайлы vs растровые тайлы, где объясняется конвейер рендеринга.

Итоги

Собственная стилизация карты не роскошь. Именно она отличает карту, похожую на сторонний виджет, от карты, которая выглядит сделанной специально для вашего продукта. С MapAtlas:

  • Спецификация стилей представляет собой стандартный JSON, совместимый с инструментами Mapbox GL JS.
  • Тёмная тема означает замену Style JSON, а не новый набор тайлов или настройку сервера.
  • Фирменные цвета применяются к дорогам, подписям и значкам POI через свойства отрисовки.
  • Собственные шрифты загружаются с любого эндпоинта глифов под вашим контролем.
  • Водяные знаки и атрибуция полностью настраиваются, white-label поддерживается на всех платных тарифах.
  • Весь стиль переключается во время работы приложения без перезагрузки страницы.

Начните создавать фирменную карту уже сегодня. Получите бесплатный API-ключ MapAtlas и возьмите базовый Style JSON за отправную точку. На первый собственный стиль уходит около 30 минут, последующие итерации занимают считанные минуты.

Часто задаваемые вопросы

Могу ли я удалить логотип MapAtlas с карты?

Да. MapAtlas позволяет создавать полностью собственные карты: вы можете полностью удалить логотип MapAtlas и заменить его на свой бренд, оставив лишь небольшую ссылку на данные OpenStreetMap, которую требует открытая лицензия.

Совместима ли стилизация MapAtlas с форматом стилей Mapbox GL JS?

Да. MapAtlas использует спецификацию стилей Mapbox, тот же JSON-формат, который используют Mapbox GL JS и MapLibre GL. Любой существующий стиль Mapbox JSON работает с MapAtlas только с обновленными URL-адресами источников.

Могу ли я переключаться между светлым и тёмным стилями карты без перезагрузки страницы?

Да. Вызовите map.setStyle() с новым URL стиля или объектом. Карта перерисовывается с новой визуальной конфигурацией без перезагрузки данных плиток, которые уже кэшированы. В сочетании с CSS-переменными это создает компонент карты, чувствительный к теме.

Оказалось полезным? Поделитесь.

Об авторе

Brent van der Heiden

Автор

Brent van der Heiden

Co-Founder & CEO at MapAtlas

Brent built MapAtlas out of a conviction that developers deserve location APIs with fair pricing and genuine end-user privacy. Before that he co-founded MapMetrics, a community mapping and navigation app. He writes about geospatial infrastructure, map data, AI search visibility, and how location data powers the products people rely on every day.

Все статьи →
Вернуться в блог