Каждая карта, которую вы видели в приложении конкурента, использует один и тот же стиль по умолчанию. Дороги стандартного бежевого цвета, вода сине-зеленого оттенка, загромождённые значки POI, которые борются за внимание с вашим интерфейсом. Это универсальные стандарты, разработанные так, чтобы никого не обидеть и не восхитить. Они чётко передают одно: этот продукт использует библиотеку карт, а не владеет опытом своей карты.
Пользовательская стилизация карты всё меняет. Карта с тёмным режимом на панели управления логистикой, сетка дорог цвета бренда на приложении недвижимости, чистый минималистичный стиль с вашим логотипом вместо водяного знака атрибуции, эти детали превращают инструмент в продукт.
В этом руководстве рассматривается спецификация стилей Mapbox в реализации MapAtlas, от структуры JSON стиля до полного переключателя свет/тьма на React. Вам не нужен опыт в ГИС. Вам нужно быть комфортным с JSON и JavaScript.
Если вы ещё не установили базовую карту, сначала начните с Как добавить интерактивные карты на ваш сайт, а затем вернитесь сюда для стилизации.
Почему стили карт по умолчанию выглядят универсально
Стиль по умолчанию поставщика плиток разработан для универсальной читаемости для самой широкой аудитории в самом широком контексте. Он приоритизирует информационную плотность над эстетическим мнением. Дороги должны быть видны. Метки должны контрастировать. Значки POI должны быть узнаваемы.
Ни одна из этих целей не совпадает с целями вашего продукта. Ваше приложение, вероятно, заботится только о небольшом подмножестве того, что находится на карте, маршрутах доставки, местоположении объектов, медицинских учреждениях, а всё остальное является визуальным шумом.
Пользовательская стилизация позволяет вам подавить то, что не нужно, подчеркнуть то, что нужно, и убедиться, что карта читается как часть вашего продукта, а не как стороннее приложение.
Понимание спецификации стилей
Стиль MapAtlas представляет собой JSON-документ с пятью ключевыми разделами:
{
"version": 8,
"name": "My Brand Style",
"sources": { ... },
"glyphs": "https://tiles.mapatlas.eu/fonts/{fontstack}/{range}.pbf?key=YOUR_API_KEY",
"sprite": "https://tiles.mapatlas.eu/sprites/basic?key=YOUR_API_KEY",
"layers": [ ... ]
}
sources— откуда приходят данные карты (векторные конечные точки плиток MapAtlas)glyphs— откуда загружаются файлы шрифтов для отображения подписейsprite— откуда загружаются изображения значков для маркеров POIlayers— упорядоченный список визуальных слоев, каждый с свойствами рисования и макета
Массив layers — это то, где вы проводите большую часть времени. Каждый слой указывает тип данных (fill, line, symbol, circle, fill-extrusion), какие функции источника отображать и как их отображать.
Вот минимальный, но полный стиль, который отображает базовую векторную плитку:
{
"version": 8,
"name": "Brand Base",
"sources": {
"mapatlas": {
"type": "vector",
"tiles": ["https://tiles.mapatlas.eu/v1/tiles/{z}/{x}/{y}.mvt?key=YOUR_API_KEY"],
"minzoom": 0,
"maxzoom": 14
}
},
"glyphs": "https://tiles.mapatlas.eu/fonts/{fontstack}/{range}.pbf?key=YOUR_API_KEY",
"sprite": "https://tiles.mapatlas.eu/sprites/basic?key=YOUR_API_KEY",
"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. Затем ссылайтесь на свои значки в слоях символов:
{
"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. Чтобы использовать пользовательский шрифт:
- Создайте файлы глифов
.pbfиз вашего шрифта, используя инструмент наподобиеfontnik. - Разместите файлы глифов на CDN или на вашем собственном сервере.
- Обновите поле
glyphsв вашем JSON стиля:
{
"glyphs": "https://your-cdn.com/fonts/{fontstack}/{range}.pbf"
}
- Ссылайтесь на шрифт в свойстве
text-fontлюбого слоя символов:
"text-font": ["Inter Bold", "Noto Sans Regular"]
Всегда предоставляйте резервный шрифт (Noto Sans охватывает символы Unicode, которые ваш основной шрифт может не включать). Модуль выбирает первый шрифт в массиве, содержащий глиф для каждого символа.
Удаление водяных знаков и атрибуции
MapAtlas позволяет полностью собственное развёртывание. Вы можете полностью удалить логотип MapAtlas с карты.
В SDK атрибуция обрабатывается управлением, которым вы можете отключить:
const map = new mapmetricsgl.Map({
container: 'map',
style: 'https://tiles.mapatlas.eu/styles/basic/style.json?key=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 при согласовании с вашим интерфейсом. В отличие от Google Maps, которая требует видимости логотипа всегда, независимо от плана, MapAtlas дает вам полный контроль.
Переключатель светлой/тёмной темы в 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://tiles.mapatlas.eu/styles/basic/style.json?key=YOUR_API_KEY',
dark: 'https://tiles.mapatlas.eu/styles/dark/style.json?key=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' ? 'Dark mode' : 'Light mode'}
</button>
</div>
);
}
Вызов setStyle перерисовывает карту с новой цветовой схемой. Данные плиток, которые уже находятся в кэше, не перезагружаются, изменяется только визуальная интерпретация.
Размещение пользовательского стиля JSON
Для полного контроля разместите ваш стиль JSON как статический файл на вашем CDN или корзине S3. Это позволяет вам:
- Контролировать версию вашего стиля вместе с кодом приложения.
- Обновлять визуальный дизайн без переразвёртывания приложения (просто обновите размещённый JSON).
- Использовать разные стили для разных сред (предпросмотр и производство).
Загрузите размещённый стиль во время выполнения:
const map = new mapmetricsgl.Map({
container: 'map',
style: 'https://your-cdn.com/styles/brand-dark.json',
center: [4.9041, 52.3676],
zoom: 12,
});
Единственное ограничение это CORS: стиль JSON должен обслуживаться с Access-Control-Allow-Origin: * (или вашим конкретным доменом), чтобы браузер мог получить его кроссдоменно.
Рабочий процесс развития стиля
Самый быстрый способ создать пользовательский стиль — это итеративный, видьте изменения в реальном времени без переписывания кода.
- Начните с базового стиля JSON MapAtlas в качестве основы. Загрузите его, получив
https://tiles.mapatlas.eu/styles/basic/style.json?key=YOUR_API_KEY. - Отредактируйте JSON в вашем редакторе, наблюдая, какой слой влияет на какой визуальный элемент.
- Перезагрузите карту вашим изменённым JSON стилем, чтобы увидеть результат.
- Когда всё стабильно, зафиксируйте стиль JSON в репозитории и разместите его на вашем CDN.
Для более глубокой настройки посмотрите документацию по визуализации и стилизации карт для полного справочника слоёв, типов свойств рисования и синтаксиса выражений.
Если вы переходите с Mapbox и задаёте себе вопрос, что изменилось, см. Mapbox vs. MapAtlas: какой API карт подходит для вашего проекта в ЕС? для прямого сравнения функций и цен.
И для архитектурного обоснования того, почему векторные плитки делают все это возможным, Векторные плитки vs. растровые плитки объясняет конвейер рендеринга подробно.
Резюме
Пользовательская стилизация карты — это не роскошь, это разница между картой, которая выглядит как стороннее приложение, и той, которая выглядит, как будто она была создана для вашего продукта. С MapAtlas:
- Спецификация стиля — это стандартный JSON, совместимый с инструментами Mapbox GL JS.
- Тёмный режим — это замена JSON стиля, а не новый набор плиток или конфигурация сервера.
- Цвета бренда применяются к дорогам, подписям и значкам POI через свойства рисования.
- Пользовательские шрифты загружаются с любой конечной точки глифов, которой вы управляете.
- Водяные знаки и атрибуция полностью настраиваются, собственный режим поддерживается на всех платных планах.
- Весь стиль можно переключать во время выполнения без перезагрузки страницы.
Начните создавать свою брендированную карту сегодня. Зарегистрируйтесь для бесплатного ключа MapAtlas API и загрузите базовый JSON стиля в качестве отправной точки. Первый пользовательский стиль займет около 30 минут, последующие итерации займут минуты.
{
"version": 8,
"name": "My Brand Style",
"sources": { ... },
"glyphs": "https://tiles.mapatlas.eu/fonts/{fontstack}/{range}.pbf?key=YOUR_API_KEY",
"sprite": "https://tiles.mapatlas.eu/sprites/basic?key=YOUR_API_KEY",
"layers": [ ... ]
}
sources, where the map data comes from (MapAtlas vector tile endpoints)glyphs, where to load font files for label renderingsprite, where to load icon images for POI markerslayers, the ordered list of visual layers, each with paint and layout properties
The layers array is where you spend most of your time. Each layer specifies a data type (fill, line, symbol, circle, fill-extrusion), which source features to draw, and how to paint them.
Here's a minimal but complete style that renders a vector tile base:
{
"version": 8,
"name": "Brand Base",
"sources": {
"mapatlas": {
"type": "vector",
"tiles": ["https://tiles.mapatlas.eu/v1/tiles/{z}/{x}/{y}.mvt?key=YOUR_API_KEY"],
"minzoom": 0,
"maxzoom": 14
}
},
"glyphs": "https://tiles.mapatlas.eu/fonts/{fontstack}/{range}.pbf?key=YOUR_API_KEY",
"sprite": "https://tiles.mapatlas.eu/sprites/basic?key=YOUR_API_KEY",
"layers": [
{
"id": "background",
"type": "background",
"paint": { "background-color": "#f5f0eb" }
}
]
}
This renders a blank canvas in your chosen background color. From here you add layers for water, landuse, roads, buildings, and labels.
Dark Mode: Changing the Core Colors
A dark mode map is not simply an inverted raster image. It's a completely different set of paint properties applied to the same vector geometry. This is one of the core reasons vector tiles exist, one tile, infinite visual interpretations.
The key colors to update for a dark theme:
| Layer | Light mode | Dark mode |
|---|---|---|
| Background (land) | #f5f0eb | #1a1a2e |
| Water | #a8d5e5 | #0d3b66 |
| Urban landuse | #e8e0d5 | #16213e |
| Parks/greenspace | #c8e6c9 | #1b4332 |
| Roads (major) | #ffffff | #3a3a5c |
| Roads (minor) | #efefef | #2d2d4a |
| Road labels | #333333 | #cccccc |
Here's how to apply this in a style layer:
{
"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]
}
}
The interpolate expression in line-width scales the road width based on zoom level, narrow at low zoom, wider as you zoom in. This is data-driven styling without any additional network requests.
Applying Brand Colors
Most design systems define a primary color (say, #97C70A), a secondary color, and a neutral palette. The map should use these same values, not approximate them.
Target these layers for brand color application:
Roads as brand elements. If your brand color is vibrant enough, use it for major roads or highlighted routes:
{
"id": "road-highlighted",
"type": "line",
"source": "mapatlas",
"source-layer": "transportation",
"filter": ["==", "class", "primary"],
"paint": {
"line-color": "#97C70A",
"line-width": 3,
"line-opacity": 0.8
}
}
Custom POI markers. Replace the default sprite icons with your own by hosting a custom sprite sheet and updating the sprite URL. Then reference your icons in symbol layers:
{
"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
}
}
Custom Fonts for Map Labels
The default map label fonts are generic. If your brand uses Inter, Roboto, or a custom typeface, you can use it for map labels too.
MapAtlas serves glyphs from its own glyph endpoint, which supports the standard Mapbox glyph format. To use a custom font:
- Generate
.pbfglyph files from your typeface using a tool likefontnik. - Host the glyph files on a CDN or your own server.
- Update the
glyphsfield in your style JSON:
{
"glyphs": "https://your-cdn.com/fonts/{fontstack}/{range}.pbf"
}
- Reference the font in any symbol layer's
text-fontproperty:
"text-font": ["Inter Bold", "Noto Sans Regular"]
Always provide a fallback font (Noto Sans covers Unicode characters your primary font may not include). The renderer uses the first font in the array that contains a glyph for each character.
Removing Watermarks and Attribution
MapAtlas allows full white-label deployment. You can remove the MapAtlas logo from the map entirely.
In the SDK, attribution is handled by a control you can disable:
const map = new mapmetricsgl.Map({
container: 'map',
style: 'https://tiles.mapatlas.eu/styles/basic/style.json?key=YOUR_API_KEY',
center: [4.9041, 52.3676],
zoom: 12,
attributionControl: false, // Remove the default attribution control
});
If you want to keep attribution but style it to match your UI, hide the default control and add your own:
map.addControl(
new mapmetricsgl.AttributionControl({
customAttribution: 'Map data © OpenStreetMap contributors',
compact: true,
}),
'bottom-left'
);
This replaces the branding with a minimal, legally compliant attribution that respects OpenStreetMap's license while matching your UI. Unlike Google Maps, which requires its logo to remain visible at all times regardless of your plan, MapAtlas gives you full control.
Light/Dark Theme Toggle in React
Here's a complete React component that manages a map with a light/dark toggle, using CSS custom properties to keep the theme in sync with the rest of your UI:
import { useEffect, useRef, useState } from 'react';
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';
const STYLES = {
light: 'https://tiles.mapatlas.eu/styles/basic/style.json?key=YOUR_API_KEY',
dark: 'https://tiles.mapatlas.eu/styles/dark/style.json?key=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' ? 'Dark mode' : 'Light mode'}
</button>
</div>
);
}
The setStyle call re-renders the map with the new color scheme. Tile data that's already in cache is not re-fetched, only the visual interpretation changes.
Hosting a Custom Style JSON
For full control, host your style JSON as a static file on your CDN or S3 bucket. This lets you:
- Version-control your style alongside your application code.
- Update the visual design without redeploying the application (just update the hosted JSON).
- Use different styles for different environments (preview vs. production).
Load a hosted style at runtime:
const map = new mapmetricsgl.Map({
container: 'map',
style: 'https://your-cdn.com/styles/brand-dark.json',
center: [4.9041, 52.3676],
zoom: 12,
});
The only constraint is CORS: the style JSON must be served with Access-Control-Allow-Origin: * (or your specific domain) so the browser can fetch it cross-origin.
Style Development Workflow
The fastest way to build a custom style is iterative, see changes in real time without rewriting code.
- Start with a MapAtlas base style JSON as your foundation. Download it by fetching
https://tiles.mapatlas.eu/styles/basic/style.json?key=YOUR_API_KEY. - Edit the JSON in your editor, watching which layer affects which visual element.
- Reload the map with your modified style JSON to see the result.
- Once stable, commit the style JSON to your repository and host it on your CDN.
For deeper customization, check the Map Visualization & Styling documentation for the full layer reference, paint property types, and expression syntax.
If you're coming from Mapbox and wondering what changed, see Mapbox vs. MapAtlas: Which Maps API Is Right for Your EU Project? for a side-by-side comparison of features and pricing.
And for the architectural underpinning of why vector tiles make all of this possible, Vector Tiles vs. Raster Tiles explains the rendering pipeline in detail.
Summary
Custom map styling is not a luxury, it's the difference between a map that feels like a third-party widget and one that feels like it was built for your product. With MapAtlas:
- The style specification is standard JSON compatible with Mapbox GL JS tooling.
- Dark mode is a style JSON swap, not a new tile set or server configuration.
- Brand colors apply to roads, labels, and POI icons through paint properties.
- Custom fonts load from any glyph endpoint you control.
- Watermarks and attribution are fully configurable, white-label is supported on all paid plans.
- The entire style can be toggled at runtime without page reload.
Start building your branded map today. Sign up for a free MapAtlas API key and load the base style JSON as your starting point. The first custom style takes about 30 minutes to get right, subsequent iterations take minutes.
Часто задаваемые вопросы
Могу ли я удалить логотип MapAtlas с карты?
Да. В отличие от Google Maps и некоторых планов Mapbox, MapAtlas позволяет создавать полностью собственные карты без обязательного водяного знака атрибуции. Вы можете полностью удалить логотип и заменить его на свой собственный бренд.
Совместима ли стилизация MapAtlas с форматом стилей Mapbox GL JS?
Да. MapAtlas использует спецификацию стилей Mapbox, тот же JSON-формат, который используют Mapbox GL JS и MapLibre GL. Любой существующий стиль Mapbox JSON работает с MapAtlas только с обновленными URL-адресами источников.
Могу ли я переключаться между светлым и тёмным стилями карты без перезагрузки страницы?
Да. Вызовите map.setStyle() с новым URL стиля или объектом. Карта перерисовывается с новой визуальной конфигурацией без перезагрузки данных плиток, которые уже кэшированы. В сочетании с CSS-переменными это создает компонент карты, чувствительный к теме.

