Skip to main content
Guides

Google Maps DrawingManager 与 API 弃用:2026 迁移指南

Drawing Library 和 Heatmap Layer 已从 Maps JavaScript API 中移除。DirectionsService 和 DistanceMatrixService 处于 Legacy 状态并已弃用。本文整理当前状态、日期和替代方案。

Brent van der Heiden最后更新 16 min read
#Google Maps API#API 迁移#DrawingManager#DirectionsService#路径规划#开发者指南
Google Maps DrawingManager 与 API 弃用:2026 迁移指南

过去十八个月里,Google 弃用了 Maps JavaScript API 中四个使用广泛的部分。其中 Heatmap Layer 和 Drawing Library 自 2026 年 5 月起已不可用。另外两个,DirectionsService 和 DistanceMatrixService,处于 Legacy 状态并已弃用,但仍可使用,也没有停用日期。

本指南列出每一项的当前状态,并附上 Google 官方页面链接,同时说明如何替换。凡是使用 MapAtlas 作为替代的地方,代码都采用我们真实的端点和响应格式。

哪些已弃用,哪些仍可使用

服务状态关键日期Google 的替代方案
Heatmap Layer已移除2025 年 5 月 27 日弃用,3.65.1c 版本(2026 年 5 月 20 日)停用deck.gl 等第三方库
Drawing Library(DrawingManager)已移除2025 年 8 月弃用,自 2026 年 5 月起不可用(3.65.3b 版本确认,2026 年 6 月 4 日)Terra Draw 等第三方库
DirectionsServiceLegacy,已弃用自 2025 年 3 月 1 日起为 Legacy,自 2026 年 2 月 25 日起弃用(3.64.2b 版本),无停用日期Routes 库中的 Route 类
DistanceMatrixServiceLegacy,已弃用自 2025 年 3 月 1 日起为 Legacy,自 2026 年 2 月 25 日起弃用(3.64.2b 版本),无停用日期Routes 库中的 RouteMatrix 类

来源:Google Maps Platform 弃用页面、Maps JavaScript API 发布说明以及 Legacy 产品页面。

Legacy 有明确含义。按照 Google 的说法,Legacy 服务不再增加新功能,也无法在新的 Cloud 项目中启用,但现有项目仍然获得支持。Google 承诺在停用此类服务前至少提前 12 个月通知,而弃用 DirectionsService 和 DistanceMatrixService 的那条发布说明也指出,目前没有停用计划,严重回归问题仍会修复。2025 年 3 月 1 日的同一次 Legacy 调整还涉及 Directions API 和 Distance Matrix API 两个 Web 服务,以及 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 年 5 月停止工作,原因就在这里。先修复它们,然后在 Google 公布日期之前规划路径规划的迁移。

Google 提供的替代方案

在路径规划方面,Google 提供两条路径,都不强制把逻辑迁移到服务器:

  • 在浏览器中: Maps JavaScript API 中的 Routes 库。Route 类替代 DirectionsService,RouteMatrix 类替代 DistanceMatrixService。
  • 在服务器上: Routes API,一个提供 Compute Routes 和 Compute Route Matrix 方法的 REST 服务。

在可视化方面,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 的路径规划端点是部署在 gateway.mapmetrics-atlas.net 上的 REST 服务,文档见 MapAtlas API 文档。它们通过查询参数接收 token,所以请从后端调用。

从 DirectionsService 迁移到 MapAtlas Directions API

迁移前(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);
    }
  }
);

迁移后(MapAtlas Directions API):

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 迁移到 MapAtlas Matrix API

MapAtlas Matrix API 一次调用即可返回每一对起点和终点之间的行程时间和距离。我们的端点将每一对的路线距离限制在 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);
        });
      });
    }
  }
);

迁移后(MapAtlas Matrix API):

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");
  });
});

这个网格与 Google 的 rows 和 elements 相对应。距离以你请求的单位返回数值,时间以秒为单位,格式化需要自行处理。

替换 Heatmap Layer

方案 1:MapLibre GL JS 热力图图层(开源)

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:deck.gl 的 HeatmapLayer,这是 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 允许用户在地图上绘制标记、线、圆和多边形。Google 弃用页面推荐的 Terra Draw 提供相同的绘制模式,并为多个地图库提供适配器,其中包括 Google Maps 和 MapLibre GL JS。绘制的形状以 GeoJSON 返回,可以直接存储,或原样发送给地理围栏或等时线服务。

成本比较

对于路径规划,Google 的 Legacy SKU 与其替代方案的 Essentials SKU 标价相同。以下价格均来自 Google Maps Platform 价格页面和 MapAtlas 价格页面,核对日期为 2026 年 9 月 26 日。

服务Google 每月免费量Google 超出后每 1,000 次(第一档)MapAtlas 每月免费量MapAtlas 超出后每 1,000 次(第一档)
Directions(Legacy)或 Compute Routes Essentials10,0005.00 美元100,000 次导航请求1.53 欧元
Directions Advanced(Legacy)或 Compute Routes Pro5,00010.00 美元同一导航档位1.53 欧元
Distance Matrix(Legacy)或 Compute Route Matrix Essentials10,000 个元素5.00 美元见价格页面见价格页面
Geocoding10,0005.00 美元25,0003.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 步:监控错误率

切换后重点关注:

  • 新 API 的 HTTP 4xx 和 5xx 比例
  • 延迟变化
  • 界面依赖的缺失字段
  • 轮渡、收费道路和限行区域等边界情况下的路线差异

第 4 步:上线前做压力测试

如果你的流量有高峰,例如物流平台早间派单时段,在依赖新 API 之前,请用峰值两倍的流量对其做压力测试。

现在该做什么

  1. 如果你仍在加载 Heatmap Layer 或 Drawing Library: 先替换它们。它们在当前版本的 Maps JavaScript API 中已无法工作。
  2. 审查路径规划代码: 找出所有对 DirectionsService、DirectionsRenderer 和 DistanceMatrixService 的调用。
  3. 选择替代方案: Route 和 RouteMatrix 类、Routes API,或其他服务商。
  4. 一次迁移一个服务,放在 feature flag 之后,切换前先比较结果。
  5. 关注 Google 的弃用页面,以便及时看到停用日期。Google 已承诺对 Legacy 服务至少提前 12 个月通知。

想试用 MapAtlas 的路径规划 API,请创建免费账户并阅读 API 文档。如需迁移方面的帮助,请通过联系页面联系我们。

常见问题

Google Maps Drawing Library 还能用吗?

不能。Google 于 2025 年 8 月弃用了 Drawing Library(包括 DrawingManager),其弃用页面将其列为自 2026 年 5 月起不可用。Maps JavaScript API 3.65.3b 版本(2026 年 6 月 4 日)的发布说明确认 DrawingManager 已不可用。Google 推荐 Terra Draw 作为替代。

Heatmap Layer 还能用吗?

不能。Google 于 2025 年 5 月 27 日弃用了 Heatmap Layer,2026 年 5 月 20 日的 3.65.1c 版本说明它已停用。Google 建议改用第三方库,例如 deck.gl 的 HeatmapLayer。

DirectionsService 和 DistanceMatrixService 什么时候停止工作?

Google 尚未确定日期。两者自 2025 年 3 月 1 日起处于 Legacy 状态,自 2026 年 2 月 25 日起被弃用。根据 Google 的发布说明,目前没有停用计划,严重回归问题仍会修复,并且在停止支持前至少提前 12 个月通知。Legacy 服务不对新的 Cloud 项目开放,因此新项目需要使用 Route 和 RouteMatrix 类或其他服务商。

可以逐步迁移吗,还是必须一次性全部切换?

可以一次迁移一个服务。每个被弃用的类彼此独立。先替换已经失效的 Drawing Library 和 Heatmap Layer,再按自己的计划替换 DirectionsService 和 DistanceMatrixService。

MapAtlas 是否支持途经点和多种出行方式?

支持。MapAtlas Directions API 接收一个有序的位置列表,首尾之间的每个点都是途经点,并支持 auto、bicycle、pedestrian、bus、truck、taxi 和 motor_scooter 等计费模型(costing)。它是一个 REST 端点,请从后端调用,避免 API 密钥暴露在客户端。

觉得有用?分享给他人吧。

关于作者

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.

查看所有文章 →
返回博客