Каждая панель логистики, объявление о недвижимости и приложение доставки имеют одно общее: карта. Если на вашем веб-сайте её ещё нет, вы упускаете важную информацию. Информацию, которая помогает пользователям понимать местоположение, близость и пространственные отношения с одного взгляда.
Это руководство проведёт вас через процесс добавления полностью интерактивной карты на любой проект JavaScript. Вы начнёте с отрендеренной карты, добавите маркеры и всплывающие окна, подключите поиск адресов с помощью API Geocoding, и закончите готовым к использованию в производстве компонентом React, который легко интегрируется с Next.js.
Вот что вы создадите в конце:
- Живую векторную карту с аутентификацией по API-ключу
- Кликабельные маркеры с пользовательским содержимым всплывающих окон
- Функцию поиска адресов, работающую с геокодированием
- Переиспользуемый компонент React с правильной очисткой и обработкой SSR для Next.js
- Контрольный список оптимизаций производительности
Предварительные требования
Перед началом убедитесь, что у вас есть:
- MapAtlas API ключ (зарегистрируйтесь бесплатно, кредитная карта не требуется). Этот единственный ключ аутентифицирует все сервисы MapAtlas: плитки, геокодирование и маршрутизацию.
- Проект JavaScript. Подойдут обычные HTML, React, Vue или Svelte.
- Node.js 18+, если вы устанавливаете через npm.
Шаг 1: Установите MapAtlas SDK
Подтяните SDK в ваш проект с помощью npm:
npm install @mapmetrics/mapmetrics-gl
Если вы работаете с обычной HTML-страницей, вставьте ссылки CDN в ваш <head>:
<link rel="stylesheet" href="https://unpkg.com/@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css" />
<script src="https://unpkg.com/@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.js"></script>
Не пропускайте импорт CSS. Без него элементы управления картой и всплывающие окна будут отрендерены без стилей. Функционально, но визуально сломано.
Шаг 2: Создайте контейнер для карты
SDK заполнит любой элемент, на который вы его указываете, поэтому вам нужен <div> с явной высотой. Это самая частая ошибка при настройке: если контейнер имеет height: 0, карта инициализируется, но остаётся невидимой.
<div id="map" style="width: 100%; height: 500px;"></div>
Фиксированное значение в пикселях или модуль viewport (100vh, 50vh) оба работают. Процентные высоты работают только если родительский элемент также имеет определённую высоту.
Шаг 3: Отрендерьте вашу первую интерактивную карту
Всего три строки конфигурации: контейнер, URL стиля с вашим API-ключом и начальную позицию.
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';
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,
});
Откройте страницу и вы увидите векторную карту, которую можно перетаскивать, прокручивать и увеличивать пальцем. Плитки загружаются по требованию с серверов MapAtlas, поэтому нет тяжелой предварительной загрузки.
Выбор стиля карты
Измените сегмент пути в URL стиля, чтобы полностью изменить внешний вид:
| Стиль | URL путь | Лучше всего для |
|---|---|---|
| Basic | /styles/basic/style.json | Приложения общего назначения |
| Bright | /styles/bright/style.json | Визуализация данных с наложениями |
| Dark | /styles/dark/style.json | Панели управления, ночной режим, аналитика |
Быстрый выигрыш: Используйте стиль Dark для панелей администратора и инструментов, используемых в условиях слабого освещения. Это снижает нагрузку на глаза и делает слои данных, такие как тепловые карты и линии маршрутов, визуально выделяющимися на фоне.
Шаг 4: Добавьте маркеры и всплывающие окна на вашу карту
Карта без маркеров это просто фоновое изображение. Маркеры превращают статичное представление во что-то, с чем пользователи могут взаимодействовать.
Одиночный маркер со всплывающим окном
const popup = new mapmetricsgl.Popup().setHTML(`
<strong>Amsterdam Central</strong>
<p>Stationsplein, 1012 AB Amsterdam</p>
`);
new mapmetricsgl.Marker({ color: '#97C70A' })
.setLngLat([4.9001, 52.3791])
.setPopup(popup)
.addTo(map);
Нажмите на маркер и всплывающее окно откроется. Вы можете поместить внутри любой HTML: адреса, миниатюры, кнопки призыва к действию, всё, что требует ваш UI.
Размещение нескольких маркеров из данных
Большинство реальных приложений требуют более одного маркера. Переберите массив и создайте маркер для каждой записи:
const locations = [
{ name: 'Amsterdam', coords: [4.9041, 52.3676] },
{ name: 'Rotterdam', coords: [4.4777, 51.9244] },
{ name: 'Utrecht', coords: [5.1214, 52.0907] },
];
locations.forEach(({ name, coords }) => {
const popup = new mapmetricsgl.Popup().setHTML(`<strong>${name}</strong>`);
new mapmetricsgl.Marker({ color: '#97C70A' })
.setLngLat(coords)
.setPopup(popup)
.addTo(map);
});
Заметка о производительности: Когда вы превышаете примерно 100-200 маркеров, отрисовка заметно замедляется при сжатых видах. Включите кластеризацию источника GeoJSON (поддерживается SDK из коробки), чтобы группировать близлежащие маркеры при низком уровне масштабирования. Проверьте документацию SDK для конфигурации кластеризации.
Шаг 5: Добавьте поиск по адресам с помощью API геокодирования
API Geocoding преобразует текстовый запрос (почтовый адрес, название города или достопримечательность) в координаты, к которым вы можете переместиться, отметить или передать в запрос маршрутизации.
async function searchAddress(query) {
const url = new URL('https://api.mapatlas.eu/geocoding/v1/search');
url.searchParams.set('text', query);
url.searchParams.set('key', 'YOUR_API_KEY');
const res = await fetch(url);
const data = await res.json();
if (!data.features.length) return;
const [lng, lat] = data.features[0].geometry.coordinates;
const label = data.features[0].properties.label;
map.flyTo({ center: [lng, lat], zoom: 14 });
new mapmetricsgl.Marker({ color: '#97C70A' })
.setLngLat([lng, lat])
.setPopup(new mapmetricsgl.Popup().setHTML(`<strong>${label}</strong>`))
.addTo(map);
}
searchAddress('Rijksmuseum, Amsterdam');
Результаты приходят обратно как объекты GeoJSON, поэтому они напрямую подходят для любого слоя, совместимого с GeoJSON, таблицы данных или последующего вызова API.
Создайте живую строку поиска менее чем за 30 строк: Подключите
searchAddressк событиюinputтекстового поля, добавьте debounce на 300ms, и у вас есть поиск карты в стиле автодополнения без дополнительных зависимостей.
Интеграция интерактивных карт с React
Переиспользуемый компонент карты
Оберните инициализацию карты в useEffect, чтобы она запустилась после монтирования DOM, и верните функцию очистки, чтобы предотвратить утечки памяти при размонтировании:
import { useEffect, useRef } from 'react';
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';
export function MapAtlasMap({ apiKey, center = [4.9041, 52.3676], zoom = 12 }) {
const containerRef = useRef(null);
useEffect(() => {
const map = new mapmetricsgl.Map({
container: containerRef.current,
style: `https://tiles.mapatlas.eu/styles/basic/style.json?key=${apiKey}`,
center, zoom,
});
return () => map.remove();
}, [apiKey]);
return <div ref={containerRef} style={{ width: '100%', height: '500px' }} />;
}
Используйте его где угодно в вашем дереве компонентов:
<MapAtlasMap apiKey={process.env.NEXT_PUBLIC_MAPATLAS_KEY} center={[4.9041, 52.3676]} zoom={13} />
Обработка Server-Side Rendering в Next.js
SDK карты зависит от API браузера (window, document), которые не существуют во время SSR. Импортируйте компонент динамически с отключённым SSR:
import dynamic from 'next/dynamic';
const MapAtlasMap = dynamic(
() => import('./MapAtlasMap').then(m => m.MapAtlasMap),
{ ssr: false, loading: () => (<div style={{ height: 500, background: '#f0f1f3', borderRadius: 12 }} />) }
);
Плейсхолдер loading сохраняет стабильность вашей разметки, пока загружается пакет карты, предотвращая кумулятивный сдвиг разметки (CLS), что важно как для пользовательского опыта, так и для Core Web Vitals.
Контрольный список производительности для производства
Перед развертыванием пройдите через эти оптимизации:
- Ленивая загрузка карт ниже сгиба. Используйте
IntersectionObserverдля инициализации карты только когда её контейнер прокручивается в поле зрения. Это откладывает примерно 200 КБ JavaScript от начальной загрузки страницы. - Придерживайтесь векторных плиток. Векторные плитки чисто масштабируются до любой плотности пикселей, загружаются быстрее растровых изображений и могут быть переоформлены на клиентской стороне без дополнительных запросов к серверу. MapAtlas по умолчанию обслуживает векторные плитки.
- Кластеризируйте большие наборы маркеров. Свыше 100-200 маркеров некластеризованная отрисовка при сжатом виде вызывает заметные падения кадров. Кластеризация полностью решает эту проблему.
- Держите ваш API-ключ на сервере. Никогда не фиксируйте ключи в открытом репозитории. Используйте переменные окружения (
NEXT_PUBLIC_MAPATLAS_KEYв Next.js) или проксируйте запросы через ваш backend для конфиденциальных операций. - Установите
maxBoundsдля региональных приложений. Если ваши пользователи заботятся только об одной географии, ограничьте viewport, чтобы плитки вне этой области никогда не запрашивались. Меньше сетевых запросов, быстрее загрузка.
Что построить дальше
У вас есть карта, которая отрендеривается, показывает маркеры, ищет адреса и интегрируется с React. Вот куда идти дальше:
- Routing API: Запросите пошаговые направления между двумя координатами. Возвращает полилинию маршрута, общее расстояние и предполагаемое время в пути.
- Isochrone API: Создайте многоугольник, охватывающий каждую точку, достижимую в течение n минут. Используется для зон доставки, карт охвата услуг и анализа потребительской области.
- Matrix API: Вычислите время в пути и расстояние между несколькими источниками и пунктами назначения в одном запросе. Необходимо для отправки флота и оптимизации логистики.
Полный справочник SDK, документация стилей и руководства API доступны на docs.mapatlas.xyz.
Часто задаваемые вопросы
Могу ли я добавить интерактивные карты на мой веб-сайт бесплатно?
Да. MapAtlas предлагает бесплатный уровень без требования кредитной карты при регистрации. Он включает отрисовку векторных плиток, API геокодирования и API маршрутизации. Этого достаточно для разработки и использования в небольших производственных масштабах.
Как встроить карту в приложение React или Next.js?
Оберните инициализацию карты в хук useEffect, чтобы она запустилась после монтирования DOM. В Next.js используйте dynamic() с ssr: false, чтобы избежать ошибок рендеринга на сервере. Оба подхода рассмотрены с примерами копирования-вставки в этом руководстве.
Что такое векторные плитки и почему их следует использовать вместо растра?
Векторные плитки описывают элементы карты (дороги, здания, метки) как математическую геометрию, а не как предварительно отрендеренные растровые изображения. Они чисто масштабируются до любого разрешения, загружаются быстрее и могут быть полностью переоформлены на клиентской стороне без дополнительных обращений к серверу.
Сколько маркеров я могу добавить, прежде чем производительность упадёт?
Отрисовка обычно деградирует свыше 100-200 маркеров при низком уровне масштабирования. Решением является кластеризация: SDK MapAtlas поддерживает кластеризацию источника GeoJSON исходно, группируя близлежащие маркеры при низком масштабировании и расширяя их по мере приближения пользователя.
Нужен ли мне опыт в ГИС для использования MapAtlas?
Нет. SDK разработан для веб-разработчиков, а не специалистов по ГИС. Вы инициализируете карту с координатами и уровнем масштабирования, добавляете маркеры с парами долготы/широты и вызываете API геокодирования с обычным текстом. Не требуется пространственных баз данных или инструментов ГИС.
