距离矩阵服务

概览

Google 的距离矩阵服务可根据指定出行方式计算多个出发地与目的地之间的行程距离和行程时长。

该服务并不会返回详细的路线信息。要获取路线信息(包括以多段线形式和文本形式表示的路线),可以向路线服务传递所需的单个出发地和目的地。

开始使用

在使用 Maps JavaScript API 中的距离矩阵服务之前,请先确保在 Google Cloud 控制台中针对您为 Maps JavaScript API 设置的同一项目启用了 Distance Matrix API。

若要查看已启用的 API 列表,请按以下步骤操作:

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

定价和政策

定价

自 2018 年 7 月 16 日起,地图、路线和地点产品开始采用全新的随用随付定价方案。如需详细了解使用 JavaScript 距离矩阵服务的新定价和用量限额,请参阅 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 对象或 Place 对象。
  • 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 对象的形式指定预期出发时间。如果 arrivalTime 已指定,系统会忽略 departureTime。如果没有为 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 字段的位置,其格式为地理编码器返回的格式。
  • rows - 一个 DistanceMatrixResponseRow 对象数组,其中每一行对应一个出发地。
  • elements - rows 的子项,对应于相应行中出发地与每个目的地的配对。其中包含每个出发地/目的地对的状态、时长、距离和票价信息(如有)。
  • 每个 element 包含均以下字段:
    • status:如需了解各种状态代码,请参阅状态代码
    • duration:该路线所需的行程时长,以 text 的形式表示,单位为秒(value 字段)。文本值的格式根据请求中指定的 unitSystem 设置(如果未提供首选项,则使用公制)。
    • duration_in_traffic:在考虑当前路况信息的情况下,该路线所需的行程时长,以 text 的形式表示,单位为秒(value 字段)。文本值的格式根据请求中指定的 unitSystem 设置(如果未提供首选项,则使用公制)。只有在路况数据可用、mode 设置为 driving 且请求的 distanceMatrixOptions 字段中包含 departureTime 的情况下,才会向 Google Maps Platform 专业版方案客户返回 duration_in_traffic
    • distance:该路线的总距离,以 text 的形式表示,单位为米 (value)。文本值的格式根据请求中指定的 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];
      }
    }
  }
}