За последние полтора года Google объявил устаревшими четыре широко используемые части Maps JavaScript API. Две из них, Heatmap Layer и Drawing Library, недоступны с мая 2026 года. Две другие, DirectionsService и DistanceMatrixService, имеют статус Legacy и считаются устаревшими, но продолжают работать, и даты отключения у них нет.
В руководстве собран текущий статус каждой функции со ссылками на страницы Google и показано, чем их заменить. Там, где замену даёт MapAtlas, код использует наши реальные эндпоинты и форматы ответов.
Что устарело и что ещё работает
| Сервис | Статус | Ключевые даты | Замена от Google |
|---|---|---|---|
| Heatmap Layer | Удалён | Устарел 27 мая 2025 года, выведен из эксплуатации в версии 3.65.1c (20 мая 2026 года) | Сторонние библиотеки, например deck.gl |
| Drawing Library (DrawingManager) | Удалена | Устарела в августе 2025 года, недоступна с мая 2026 года (подтверждено в версии 3.65.3b, 4 июня 2026 года) | Сторонние библиотеки, например Terra Draw |
| DirectionsService | Legacy, устарел | Legacy с 1 марта 2025 года, устарел с 25 февраля 2026 года (версия 3.64.2b), даты отключения нет | Класс Route в библиотеке Routes |
| DistanceMatrixService | Legacy, устарел | Legacy с 1 марта 2025 года, устарел с 25 февраля 2026 года (версия 3.64.2b), даты отключения нет | Класс RouteMatrix в библиотеке Routes |
Источники: страница устаревших функций Google Maps Platform, примечания к выпускам Maps JavaScript API и страница продуктов Legacy.
У статуса Legacy есть точное значение. По словам Google, сервис Legacy больше не получает новых функций и не включается в новых проектах Cloud, но в существующих проектах поддержка сохраняется. Google обещает предупреждать минимум за 12 месяцев до вывода такого сервиса из эксплуатации. В примечании к выпуску, где DirectionsService и DistanceMatrixService объявлены устаревшими, сказано, что их отключение не запланировано и серьёзные регрессии будут исправляться. Тот же переход в Legacy 1 марта 2025 года затронул веб-сервисы Directions API и Distance Matrix API, а также Places API и JavaScript Places Service.
Что ломается
Этот код уже не работает в актуальных версиях Maps JavaScript API:
// Removed in 2026: these constructors no longer work
const heatmap = new google.maps.visualization.HeatmapLayer({ data: points });
const drawingManager = new google.maps.drawing.DrawingManager();
Этот код по-прежнему работает в существующих проектах, но устарел и не заработает в новом проекте Cloud:
// Legacy and deprecated, no shutdown date yet
const directionsService = new google.maps.DirectionsService();
const distanceMatrixService = new google.maps.DistanceMatrixService();
Если тепловая карта или инструмент рисования на вашем сайте перестали работать в мае 2026 года, причина в этом. Исправьте их в первую очередь. Затем спланируйте миграцию маршрутизации, пока Google не объявил дату.
Замены от Google
Для маршрутизации Google предлагает два пути, и ни один не заставляет переносить логику на сервер:
- В браузере: библиотека Routes в Maps JavaScript API. Класс
Routeзаменяет DirectionsService, а классRouteMatrixзаменяет DistanceMatrixService. - На сервере: Routes API, REST-сервис с методами Compute Routes и Compute Route Matrix.
Для визуализации у Google больше нет собственного решения. Страница о тепловой карте отсылает к deck.gl, а страница устаревших функций называет Terra Draw для рисования.
Чек-лист миграции
1. Проверьте кодовую базу
Найдите затронутые классы:
# Find all files using deprecated Google Maps services
grep -rn "DirectionsService\|DistanceMatrixService\|DirectionsRenderer\|HeatmapLayer\|DrawingManager" \
--include="*.js" --include="*.ts" --include="*.tsx" --include="*.jsx" src/
Запишите все файлы и компоненты, которые их используют, и отметьте, где выполняется вызов: в браузере или на сервере.
2. Опишите, как используется каждый сервис
Для каждого случая зафиксируйте:
- Способы передвижения (автомобиль, пешком, велосипед, общественный транспорт)
- Промежуточные точки (простой маршрут из A в B или маршрут с несколькими остановками)
- Поля ответа, которые вы читаете (расстояние, время, полилиния, шаги, стоимость проезда)
- Объём (запросы в день и в месяц, для оценки затрат)
- Требования к задержке (ответ пользователю в реальном времени или пакетная обработка)
3. Выберите цель
Вариант A: остаться в Google. Перейдите на классы Route и RouteMatrix или на Routes API. Сверьте используемые поля с руководствами по миграции, потому что форматы ответов отличаются от классов Legacy.
Вариант B: сменить поставщика. Интеграцию всё равно придётся переписать, поэтому сравните поставщиков по требованиям из шага 2.
4. Запустите старую и новую версии параллельно
Не мигрируйте на месте. Какое-то время запускайте обе реализации параллельно и сравнивайте расстояние, время и задержку на реальных маршрутах, прежде чем переключаться.
5. Обновите обработку ошибок
Классы Legacy сообщали об ошибках через значение статуса в колбэке. REST-замены возвращают HTTP-коды и тело ошибки, поэтому обработку ошибок нужно изменить.
Замена каждого сервиса на MapAtlas
Эндпоинты маршрутизации MapAtlas работают как REST-сервисы на gateway.mapmetrics-atlas.net и описаны в документации API MapAtlas. Они принимают токен как параметр запроса, поэтому вызывайте их с бэкенда.
С DirectionsService на Directions API от MapAtlas
До (Google, Legacy):
const directionsService = new google.maps.DirectionsService();
directionsService.route(
{
origin: { lat: 52.52, lng: 13.405 },
destination: { lat: 48.8566, lng: 2.3522 },
travelMode: google.maps.TravelMode.DRIVING,
waypoints: [
{ location: { lat: 50.9375, lng: 6.9603 }, stopover: true }
],
},
(result, status) => {
if (status === "OK") {
const route = result.routes[0];
console.log("Distance:", route.legs[0].distance.text);
console.log("Duration:", route.legs[0].duration.text);
}
}
);
После (Directions API от MapAtlas):
const response = await fetch(
`https://gateway.mapmetrics-atlas.net/directions/?token=${process.env.MAPATLAS_API_KEY}`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
// Ordered stops: origin, waypoints, destination
locations: [
{ lat: 52.52, lon: 13.405 },
{ lat: 50.9375, lon: 6.9603 },
{ lat: 48.8566, lon: 2.3522 },
],
costing: "auto", // auto, bicycle, pedestrian, bus, truck, taxi, motor_scooter
units: "kilometers",
}),
}
);
const { trip } = await response.json();
console.log("Distance (km):", trip.summary.length);
console.log("Duration (s):", trip.summary.time);
// Each leg carries its geometry as an encoded polyline (precision 6)
const shapes = trip.legs.map((leg) => leg.shape);
Основные отличия:
- REST-вызов вместо класса JavaScript, выполняется с вашего бэкенда.
- Промежуточные точки задаются средними элементами
locations. - Другая структура ответа. Итоги находятся в
trip.summary, а у каждого участка есть закодированная полилиния вshape. Декодируйте её перед отрисовкой маршрута (см. пример бэкенда ниже).
С DistanceMatrixService на Matrix API от MapAtlas
Matrix API от MapAtlas возвращает время в пути и расстояние для каждой пары точки отправления и назначения за один вызов. Наш эндпоинт ограничивает каждую пару 400 км по маршруту, поэтому в примере используются места вокруг Берлина.
До (Google, Legacy):
const service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [
{ lat: 52.52, lng: 13.405 },
{ lat: 52.3906, lng: 13.0645 },
],
destinations: [
{ lat: 51.3397, lng: 12.3731 },
{ lat: 51.0504, lng: 13.7373 },
],
travelMode: google.maps.TravelMode.DRIVING,
},
(response, status) => {
if (status === "OK") {
response.rows.forEach((row, i) => {
row.elements.forEach((element, j) => {
console.log(`Origin ${i} -> Dest ${j}:`,
element.distance.text, element.duration.text);
});
});
}
}
);
После (Matrix API от MapAtlas):
const response = await fetch(
`https://gateway.mapmetrics-atlas.net/matrix/?token=${process.env.MAPATLAS_API_KEY}`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
sources: [
{ lat: 52.52, lon: 13.405 },
{ lat: 52.3906, lon: 13.0645 },
],
targets: [
{ lat: 51.3397, lon: 12.3731 },
{ lat: 51.0504, lon: 13.7373 },
],
costing: "auto",
units: "kilometers",
}),
}
);
const data = await response.json();
// One row per source, one cell per target
data.sources_to_targets.forEach((row: any[], i: number) => {
row.forEach((cell, j) => {
console.log(`Origin ${i} -> Dest ${j}:`, cell.distance, "km", cell.time, "s");
});
});
Сетка соответствует rows и elements у Google. Расстояния приходят числами в запрошенных единицах, а время в секундах, так что форматирование остаётся за вами.
Замена Heatmap Layer
Вариант 1: слой тепловой карты в MapLibre GL JS (open source)
import maplibregl from "maplibre-gl";
const map = new maplibregl.Map({
container: "map",
style: "https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_ACCOUNT_ID/mapstyle.json&token=YOUR_API_KEY",
center: [13.405, 52.52],
zoom: 10,
});
map.on("load", () => {
map.addSource("heat-data", {
type: "geojson",
data: {
type: "FeatureCollection",
features: heatmapPoints.map((point) => ({
type: "Feature",
geometry: { type: "Point", coordinates: [point.lng, point.lat] },
properties: { weight: point.weight },
})),
},
});
map.addLayer({
id: "heatmap-layer",
type: "heatmap",
source: "heat-data",
paint: {
"heatmap-weight": ["get", "weight"],
"heatmap-intensity": 1,
"heatmap-radius": 20,
"heatmap-opacity": 0.7,
},
});
});
Тепловую карту отрисовывает сама картографическая библиотека, дополнительный сервис не нужен.
Вариант 2: HeatmapLayer из deck.gl, который предлагает документация Google:
import { HeatmapLayer } from "@deck.gl/aggregation-layers";
const heatmapLayer = new HeatmapLayer({
data: heatmapPoints,
getPosition: (d) => [d.lng, d.lat],
getWeight: (d) => d.weight,
radiusPixels: 30,
});
Оба варианта работают. MapLibre GL JS напрямую читает стили MapAtlas, а deck.gl можно наложить на любую базовую карту.
Замена Drawing Library
DrawingManager позволял пользователям рисовать на карте маркеры, линии, круги и полигоны. Terra Draw, библиотека, которую называет страница устаревших функций Google, поддерживает те же режимы и имеет адаптеры для нескольких картографических библиотек, включая Google Maps и MapLibre GL JS. Фигуры возвращаются в формате GeoJSON, который можно сохранить или без изменений отправить в сервис геозон или изохрон.
Сравнение затрат
Прайс-лист Google одинаков для Legacy-SKU маршрутизации и для Essentials-SKU их замен. Все цены ниже взяты со страницы цен Google Maps Platform и страницы цен MapAtlas, обе проверены 26 сентября 2026 года.
| Сервис | Google, бесплатно в месяц | Google, за 1 000 сверх лимита (первая ступень) | MapAtlas, бесплатно в месяц | MapAtlas, за 1 000 сверх лимита (первая ступень) |
|---|---|---|---|---|
| Directions (Legacy) или Compute Routes Essentials | 10 000 | 5,00 $ | 100 000 навигационных запросов | 1,53 € |
| Directions Advanced (Legacy) или Compute Routes Pro | 5 000 | 10,00 $ | Та же навигационная ступень | 1,53 € |
| Distance Matrix (Legacy) или Compute Route Matrix Essentials | 10 000 элементов | 5,00 $ | См. страницу цен | См. страницу цен |
| Geocoding | 10 000 | 5,00 $ | 25 000 | 3,90 € |
Google выставляет счета в долларах США, а MapAtlas в евро, поэтому перед сравнением пересчитайте валюту. Оба снижают тарифы при росте объёма. Пример расчёта для 500 000 запросов маршрута в месяц:
- Google Compute Routes Essentials: 10 000 бесплатно, 90 000 по 5,00 $ и 400 000 по 4,00 $, итого 2 050 $.
- Навигация MapAtlas: 100 000 бесплатно и 400 000 по 1,53 €, итого около 610 €.
Полный пример: маршрут на бэкенде и карта
Эта схема держит ключ API на сервере и отправляет в браузер только геометрию маршрута.
Маршрут API на бэкенде (Next.js)
// app/api/directions/route.ts
import { NextRequest, NextResponse } from "next/server";
// Decode an encoded polyline with precision 6 into [lon, lat] pairs
function decodePolyline6(str: string): [number, number][] {
const coords: [number, number][] = [];
let index = 0, lat = 0, lng = 0;
while (index < str.length) {
for (const axis of [0, 1]) {
let result = 0, shift = 0, byte: number;
do {
byte = str.charCodeAt(index++) - 63;
result |= (byte & 0x1f) << shift;
shift += 5;
} while (byte >= 0x20);
const delta = result & 1 ? ~(result >> 1) : result >> 1;
if (axis === 0) lat += delta; else lng += delta;
}
coords.push([lng / 1e6, lat / 1e6]);
}
return coords;
}
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const [oLat, oLon] = searchParams.get("origin")!.split(",").map(Number);
const [dLat, dLon] = searchParams.get("destination")!.split(",").map(Number);
const response = await fetch(
`https://gateway.mapmetrics-atlas.net/directions/?token=${process.env.MAPATLAS_API_KEY}`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
locations: [{ lat: oLat, lon: oLon }, { lat: dLat, lon: dLon }],
costing: "auto",
units: "kilometers",
}),
}
);
if (!response.ok) {
return NextResponse.json({ error: "routing failed" }, { status: 502 });
}
const { trip } = await response.json();
const coordinates = trip.legs.flatMap((leg: { shape: string }) => decodePolyline6(leg.shape));
return NextResponse.json({
coordinates,
distanceKm: trip.summary.length,
durationS: trip.summary.time,
});
}
Компонент карты (React и MapLibre GL JS)
import { useEffect, useRef } from "react";
import maplibregl from "maplibre-gl";
function DirectionsMap({ origin, destination }: {
origin: { lat: number; lng: number };
destination: { lat: number; lng: number };
}) {
const mapRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const map = new maplibregl.Map({
container: mapRef.current!,
style: "https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_ACCOUNT_ID/mapstyle.json&token=YOUR_API_KEY",
center: [origin.lng, origin.lat],
zoom: 7,
});
map.on("load", async () => {
const res = await fetch(
"/api/directions?" +
new URLSearchParams({
origin: `${origin.lat},${origin.lng}`,
destination: `${destination.lat},${destination.lng}`,
})
);
if (!res.ok) return;
const { coordinates } = await res.json();
map.addSource("route", {
type: "geojson",
data: {
type: "Feature",
geometry: { type: "LineString", coordinates },
properties: {},
},
});
map.addLayer({
id: "route-line",
type: "line",
source: "route",
paint: { "line-color": "#4A90D9", "line-width": 5 },
});
const bounds = coordinates.reduce(
(b: maplibregl.LngLatBounds, coord: [number, number]) => b.extend(coord),
new maplibregl.LngLatBounds(coordinates[0], coordinates[0])
);
map.fitBounds(bounds, { padding: 50 });
});
return () => map.remove();
}, [origin, destination]);
return <div ref={mapRef} style={{ width: "100%", height: "400px" }} />;
}
Как протестировать миграцию
Шаг 1: сравните обе реализации
В течение тестового периода вызывайте старый и новый сервис с одинаковыми запросами. Логируйте расстояние и время из обоих ответов и изучайте расхождения на реальных маршрутах, особенно с паромами, платными участками и дорогами с ограниченным доступом.
Шаг 2: используйте feature flag
Спрячьте выбор поставщика за флагом, чтобы откатиться без деплоя:
const useMapAtlasDirections = process.env.FEATURE_MAPATLAS_DIRECTIONS === "true";
const directions = useMapAtlasDirections
? await fetchMapAtlasDirections(origin, destination)
: await fetchGoogleDirections(origin, destination);
Шаг 3: следите за долей ошибок
После переключения отслеживайте:
- Долю ответов HTTP 4xx и 5xx от нового API
- Изменения задержки
- Отсутствующие поля, которые читает ваш интерфейс
- Расхождения маршрутов в пограничных случаях: паромы, платные дороги, зоны с ограниченным доступом
Шаг 4: нагрузочный тест перед запуском
Если у вас бывают пики трафика, например при утренней диспетчеризации на логистической платформе, проведите нагрузочный тест нового API на удвоенном пиковом объёме, прежде чем на него полагаться.
Что делать сейчас
- Если вы всё ещё загружаете Heatmap Layer или Drawing Library: замените их в первую очередь. В актуальных версиях Maps JavaScript API они больше не работают.
- Проверьте код маршрутизации: найдите каждый вызов DirectionsService, DirectionsRenderer и DistanceMatrixService.
- Выберите замену: классы
RouteиRouteMatrix, Routes API или другого поставщика. - Мигрируйте по одному сервису, за feature flag, и сравнивайте результаты перед переключением.
- Следите за страницей устаревших функций Google, чтобы не пропустить дату отключения. Для сервисов Legacy Google обещает предупреждение минимум за 12 месяцев.
Чтобы попробовать API маршрутизации MapAtlas, создайте бесплатный аккаунт и изучите документацию API. За помощью с миграцией обращайтесь через страницу контактов.
Часто задаваемые вопросы
Доступна ли ещё Drawing Library в Google Maps?
Нет. Google объявил Drawing Library, включая DrawingManager, устаревшей в августе 2025 года, и на странице устаревших функций она значится недоступной с мая 2026 года. Примечания к версии 3.65.3b Maps JavaScript API (4 июня 2026 года) подтверждают, что DrawingManager больше не доступен. В качестве альтернативы Google называет Terra Draw.
Доступен ли ещё Heatmap Layer?
Нет. Google объявил Heatmap Layer устаревшим 27 мая 2025 года, а в версии 3.65.1c от 20 мая 2026 года он выведен из эксплуатации. Вместо него Google предлагает сторонние библиотеки, например HeatmapLayer из deck.gl.
Когда перестанут работать DirectionsService и DistanceMatrixService?
Google не назвал дату. Оба сервиса имеют статус Legacy с 1 марта 2025 года и считаются устаревшими с 25 февраля 2026 года. Согласно примечаниям к выпуску, отключение не запланировано, серьёзные регрессии продолжат исправлять, а о прекращении поддержки предупредят минимум за 12 месяцев. Сервисы Legacy недоступны в новых проектах Cloud, поэтому новому проекту нужны классы Route и RouteMatrix или другой поставщик.
Можно ли мигрировать постепенно или нужно менять всё сразу?
Мигрировать можно по одному сервису. Каждый устаревший класс независим. Сначала замените уже удалённые Drawing Library и Heatmap Layer, потому что они не работают, а затем DirectionsService и DistanceMatrixService в удобные для вас сроки.
Поддерживает ли MapAtlas промежуточные точки и разные способы передвижения?
Да. Directions API от MapAtlas принимает упорядоченный список точек, так что каждая точка между первой и последней служит промежуточной. Поддерживаются модели стоимости auto, bicycle, pedestrian, bus, truck, taxi и motor_scooter. Это REST-эндпоинт, поэтому вызывайте его с бэкенда, чтобы ключ API не попадал к клиенту.

