距离矩阵服务

概览

Google 的距离矩阵服务使用给定的出行方式计算多个出发地和目的地之间的行程距离和行程时长。

该服务并不会返回详细的路线信息。将所需的单个出发地和目的地传递给路线服务,即可获取路线信息(包括多段线和文本路线)。

开始使用

在 Maps JavaScript API 中使用距离矩阵服务之前,首先确保在 Google Cloud Console 中启用了 Maps JavaScript API 的同一项目中启用了 Distance Matrix API。

要查看已启用 API 的列表,请执行以下操作:

  1. 转到 Google Cloud Console
  2. 点击选择项目按钮,然后选择您为 Maps JavaScript API 设置的同一项目,然后点击打开
  3. 信息中心的 API 列表中,查找 Distance Matrix API
  4. 如果您在列表中看到了该 API,就说明一切就绪。如果未列出该 API,请启用:
    1. 在页面顶部,选择 ENABLE API 以显示标签页。或从左侧菜单中选择
    2. 搜索 Distance Matrix API,然后从结果列表中选择它。
    3. 选择启用。该过程完成后,Distance Matrix API 会显示在信息中心的 API 列表中。

价格和政策

价格

自 2018 年 7 月 16 日起,地图、路线和地点产品将采用全新的随用随付定价方案。如需详细了解使用 JavaScript 距离矩阵服务的新价格和用量限额,请参阅 Distance Matrix API 的用量和结算

注意:发送到距离矩阵服务的每个查询都受允许元素数量限制,其中“出发地”数量乘以“目的地”数量即是元素数量。

速率限制

对于其他请求的限制,请注意以下几点:

无论有多少用户共享同一项目,都按用户会话应用速率限制。首次加载 API 时,系统会为您分配初始元素配额。您使用此配额后,该 API 会对每秒的请求施加速率限制。如果某个时间段内发出的请求过多,API 会返回 OVER_QUERY_LIMIT 响应代码。

基于会话的速率限制可防止将客户端服务用于批量请求。对于批量请求,请使用 Distance Matrix API 网络服务

政策

使用距离矩阵服务必须遵循为 Distance Matrix API 描述的政策

距离矩阵请求

Google Maps API 需要调用外部服务器,因此对距离矩阵服务的访问是异步进行的。因此,您需要传递一个要在请求完成后执行的回调方法来处理结果。

您可以通过 google.maps.DistanceMatrixService 构造函数对象在您的代码中访问距离矩阵服务。DistanceMatrixService.getDistanceMatrix() 方法会向距离矩阵服务发起请求,方法是向其传递一个 DistanceMatrixRequest 对象字面量,其中包含起点、终点和出行方式,以及用于在收到响应后执行的回调方法。

var origin1 = new google.maps.LatLng(55.930385, -3.118425);
var origin2 = 'Greenwich, England';
var destinationA = 'Stockholm, Sweden';
var destinationB = new google.maps.LatLng(50.087692, 14.421150);

var service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
  {
    origins: [origin1, origin2],
    destinations: [destinationA, destinationB],
    travelMode: 'DRIVING',
    transitOptions: TransitOptions,
    drivingOptions: DrivingOptions,
    unitSystem: UnitSystem,
    avoidHighways: Boolean,
    avoidTolls: Boolean,
  }, callback);

function callback(response, status) {
  // See Parsing the Results for
  // the basics of a callback function.
}

查看示例

DistanceMatrixRequest 包含以下字段:

  • origins(必需)- 包含一个或多个地址字符串的数组、google.maps.LatLng 对象或根据其计算距离和时间的 Place 对象。
  • destinations(必需)- 包含一个或多个地址字符串、google.maps.LatLng 对象或地点对象的数组,用于计算距离和时间。
  • travelMode(可选)- 计算路线时使用的交通方式。请参阅有关出行方式的部分。
  • transitOptions(可选)- 仅适用于 travelModeTRANSIT 的请求。公交选项部分介绍了有效值。
  • drivingOptions(可选)指定仅适用于 travelModeDRIVING 的请求的值。驾驶选项部分介绍了有效值。
  • unitSystem(可选)- 显示距离时使用的单位制。接受的值包括:
    • google.maps.UnitSystem.METRIC(默认)
    • google.maps.UnitSystem.IMPERIAL
  • avoidHighways(可选)- 如果设置为 true,系统将计算起点和终点之间的路线,以尽可能避开高速公路。
  • avoidTolls(可选)- 如果设置为 true,系统将尽可能使用非收费路线计算点之间的路线。

出行模式

计算时间和距离时,您可以指定要使用的交通模式。目前支持以下出行方式:

  • BICYCLING 通过自行车道和首选街道请求骑行路线(目前仅在美国和加拿大的某些城市提供)。
  • DRIVING(默认)指示使用道路网络的标准行车路线。
  • TRANSIT 请求通过公交路线查询路线。只有当请求中包含 API 密钥时,才能指定此选项。如需了解此类请求的可用选项,请参阅公交选项部分。
  • WALKING 请求通过步道和人行道(如果有)的步行路线。

公共交通选项

公交服务目前处于“实验性”阶段。在此阶段,我们将实施速率限制以防止 API 滥用。我们最终会根据 API 的合理使用情况对每个地图加载的总查询次数设定上限。

可用的距离矩阵请求选项因出行模式而异。在公交请求中,avoidHighwaysavoidTolls 选项将被忽略。您可以通过 TransitOptions 对象字面量指定特定于公交的路由选项。

公交请求具有时效性。系统仅会针对未来的时间返回计算结果。

TransitOptions 对象字面量包含以下字段:

{
  arrivalTime: Date,
  departureTime: Date,
  modes: [transitMode1, transitMode2]
  routingPreference: TransitRoutePreference
}

这些字段的含义如下:

  • arrivalTime(可选)以 Date 对象的形式指定所需的到达时间。如果指定到达时间,系统会忽略出发时间。
  • departureTime(可选)以 Date 对象的形式指定期望的出发时间。如果指定了 arrivalTimedepartureTime 将被忽略。如果未为 departureTimearrivalTime 指定任何值,则默认值为现在(即当前时间)。
  • modes(可选)是包含一个或多个 TransitMode 对象字面量的数组。只有在请求中包含 API 密钥时,才可以添加此字段。每个 TransitMode 均指定首选交通方式。允许使用以下值:
    • BUS 表示计算的路线应首选公交车出行。
    • RAIL 表示计算的路线应首选火车、电车、轻轨和地铁出行。
    • SUBWAY 表示计算的路线应首选地铁出行。
    • TRAIN 表示计算的路线应首选火车出行。
    • TRAM 表示计算的路线应首选有轨电车和轻轨出行。
  • routingPreference(可选)指定公交路线的偏好设置。使用此选项,您可以自定义返回的选项,而不是接受 API 选择的默认最佳路线。 只有在请求中包含 API 密钥时,才能指定此字段。允许使用以下值:
    • FEWER_TRANSFERS 表示计算的路由应首选有限数量的传输。
    • LESS_WALKING 表示计算的路线应首选有限的步行距离。

行车选项

使用 drivingOptions 对象指定出发时间,在给定预期路况条件的情况下,计算前往目的地的最佳路线。您还可以指定流量的预计使用时间是基于悲观、乐观的还是根据历史交通状况和实时路况做出的最佳预估。

drivingOptions 对象包含以下字段:

{
  departureTime: Date,
  trafficModel: TrafficModel
}

这些字段的含义如下:

  • departureTime必须使 drivingOptions 对象字面量有效)以 Date 对象的形式指定所需的出发时间。该值必须设置为当前时间或未来的某个时间,而不能是过去的时间。(API 会将所有日期转换为 UTC,以确保跨时区一致处理。)如果您在请求中包含 departureTime,该 API 会根据当时的预期路况条件返回最佳路线,并在响应中加入预计的路况时间 (duration_in_traffic)。如果您未指定出发时间(即请求不包含 drivingOptions),则返回的路线通常是不考虑路况条件的常规路线。

    注意:如果未指定出发时间,则系统会根据道路网络和与时间无关的平均交通状况来选择路线和持续时间。随着时间的推移,给定请求的结果可能会发生变化,因为道路网络、平均交通状况更新和服务的分布情况。在任意时间或频率下,结果可能也几乎相同。

  • trafficModel(可选)指定在计算交通时间时使用的假设。此设置会影响响应中 duration_in_traffic 字段中返回的值,该值包含根据历史平均值预测的流量。默认为 best_guess。允许使用以下值:
    • bestguess(默认)表示返回的 duration_in_traffic 应该是根据已知交通状况和实时路况信息得出的最佳出行时间估算值。departureTime 越接近当前时间,实时流量就越重要。
    • pessimistic 表示在大多数情况下返回的 duration_in_traffic 应该比实际出行时间更长,但交通状况特别糟糕的少数日期有时可能会超过此值。
    • optimistic 表示在大多数日子里返回的 duration_in_traffic 应该短于实际行程时间,但在交通状况特别好的日子里,偶尔偶尔会比该值更快。

下面是行车路线的 DistanceMatrixRequest 示例,包括出发时间和路况模型:

{
  origins: [{lat: 55.93, lng: -3.118}, 'Greenwich, England'],
  destinations: ['Stockholm, Sweden', {lat: 50.087, lng: 14.421}],
  travelMode: 'DRIVING',
  drivingOptions: {
    departureTime: new Date(Date.now() + N),  // for the time N milliseconds from now.
    trafficModel: 'optimistic'
  }
}

距离矩阵响应

如果成功调用距离矩阵服务,则返回 DistanceMatrixResponse 对象和 DistanceMatrixStatus 对象。这些信息会传递到您在请求中指定的回调函数。

DistanceMatrixResponse 对象包含可计算路线的每个起点/终点对的距离和时长信息。

{
  "originAddresses": [ "Greenwich, Greater London, UK", "13 Great Carleton Square, Edinburgh, City of Edinburgh EH16 4, UK" ],
  "destinationAddresses": [ "Stockholm County, Sweden", "Dlouhá 609/2, 110 00 Praha-Staré Město, Česká republika" ],
  "rows": [ {
    "elements": [ {
      "status": "OK",
      "duration": {
        "value": 70778,
        "text": "19 hours 40 mins"
      },
      "distance": {
        "value": 1887508,
        "text": "1173 mi"
      }
    }, {
      "status": "OK",
      "duration": {
        "value": 44476,
        "text": "12 hours 21 mins"
      },
      "distance": {
        "value": 1262780,
        "text": "785 mi"
      }
    } ]
  }, {
    "elements": [ {
      "status": "OK",
      "duration": {
        "value": 96000,
        "text": "1 day 3 hours"
      },
      "distance": {
        "value": 2566737,
        "text": "1595 mi"
      }
    }, {
      "status": "OK",
      "duration": {
        "value": 69698,
        "text": "19 hours 22 mins"
      },
      "distance": {
        "value": 1942009,
        "text": "1207 mi"
      }
    } ]
  } ]
}

距离矩阵结果

响应中受支持的字段解释如下:

  • originAddresses 是一个数组,其中包含距离矩阵请求的 origins 字段中传递的位置。这些地址将按照地理编码器所设置的格式返回
  • destinationAddresses 是一个数组,其中包含 destinations 字段中传递的位置(采用地理编码器返回的格式)。
  • rowsDistanceMatrixResponseRow 对象的数组,其中每行对应一个起点。
  • elementsrows 的子项,对应于该行的源与每个目的地的配对。其中包含每个起点/终点对的状态、时长、距离和费用信息(如果有)。
  • 每个 element 包含以下字段:
    • status:如需查看可能的状态代码列表,请参阅状态代码
    • duration:该路线的行程时长,以秒(value 字段)的形式表示,格式为 text。文本值的格式根据请求中指定的 unitSystem 设置(如果未提供偏好设置,则使用公制)。
    • duration_in_traffic:考虑当前路况时此路线行驶所用的时间长度,以秒为单位(value 字段)并以 text 的形式表示。文本值的格式根据请求中指定的 unitSystem 设置(如果未提供偏好设置,则使用公制)。duration_in_traffic 只会返回到有流量数据的 Google Maps Platform 高级计划客户,mode 设置为 driving,且 departureTime 包含在请求的 distanceMatrixOptions 字段中。
    • distance:此路线的总距离,以米 (value) 为单位并以 text 表示。文本值的格式根据请求中指定的 unitSystem 设置(如果未提供偏好设置,则使用公制)。
    • fare:包含此路线的总费用(即总票价)。仅针对公交请求返回此属性,且仅针对提供票价信息的公交提供商返回此属性。这些信息包括:
      • currencyISO 4217 货币代码,用于表示金额所用的货币。
      • value:总票价金额,以上述货币为单位。

状态代码

距离矩阵响应包含整个响应的状态代码,以及每个元素的状态。

响应状态代码

适用于 DistanceMatrixResponse 的状态代码在 DistanceMatrixStatus 对象中传递,其中包含:

  • OK,表示请求有效。即使未在任何源站和目的地之间找到任何路由,系统也会返回此状态。如需了解元素级状态信息,请参阅元素状态代码
  • INVALID_REQUEST - 提供的请求无效。通常是因为缺少必填字段。请参阅上文支持的字段列表
  • MAX_ELEMENTS_EXCEEDED - 出发地和目的地的乘积超过了每次查询限制
  • MAX_DIMENSIONS_EXCEEDED - 您的请求包含的源站超过 25 个,或目的地超过 25 个。
  • OVER_QUERY_LIMIT - 您的应用在允许的时间段内请求的元素过多。如果您在一段合理的时间后重试,请求应该会成功。
  • REQUEST_DENIED - 该服务拒绝您的网页使用距离矩阵服务。
  • UNKNOWN_ERROR - 由于服务器错误,系统无法处理距离矩阵请求。如果您重试一次,该请求可能会成功。

元素状态代码

以下状态代码适用于特定的 DistanceMatrixElement 对象:

  • NOT_FOUND - 无法对此配对的起点和/或终点进行地理编码。
  • OK,表示该响应包含的结果有效。
  • ZERO_RESULTS - 在源站和目的地之间找不到路由。

解析结果

DistanceMatrixResponse 对象包含请求中传递的每个源站的一个 row。该行的每个源对与提供的目的地配对时,每行都包含一个 element 字段。

function callback(response, status) {
  if (status == 'OK') {
    var origins = response.originAddresses;
    var destinations = response.destinationAddresses;

    for (var i = 0; i < origins.length; i++) {
      var results = response.rows[i].elements;
      for (var j = 0; j < results.length; j++) {
        var element = results[j];
        var distance = element.distance.text;
        var duration = element.duration.text;
        var from = origins[i];
        var to = destinations[j];
      }
    }
  }
}