Google Maps API 研究

blur cartography close up concept
Photo by slon_dot_pics on Pexels.com

最近准备调用一些Google Maps中的数据,主要是想研究一下路线中的公交信息。

Google Maps API提供了多种方法来测算两点之间的导航数据,主要的模块是DirectionService,用来与用户交换请求与返回信息。返回值内包括Travel timeDistancenumber of turns等多个信息。得到之后除了自己处理之外,也可以通过DirectionsRenderer来渲染(render)这些返回值。

当在向API提供的请求内指定出发地和目的地时,可以用一个非常明确的字符串(如”Chicago, IL”或”Darwin, NSW, Australia”),一组经纬度,或一个google.maps.Place信息。

导航模块可以利用一系列路径点在地图上画出一条路径,也可以在一组

 

元素内辅助文字表述(如“在Williamsburg Bridge处向右转”)。

下面让我们开始吧

在使用导航模块之前,先要确保在Google Cloud Platform Console中激活Directions API,并与Maps JavaScript API同属一个项目。

可以通过下述步骤查看被激活的API:

  1. 前往Google Cloud Platform Console
  2. 点击「选择一个项目(Select a project)」按键,然后在Maps JavaScript API所属的项目中点击「打开(Open)」
  3. 「控制面板(Dashboard)」的API列表中,找到「导航API(Directions API)」
  4. 如果可以找到这个API,就证明这一环节已经可以通过了。如果没有这个API,可以激活它:
    • 在页面顶部,选择「激活API(ENABLE API)」以显示出「库「Library」」标签。或者从左侧的菜单栏中选择「库「Library」」。
    • 搜索「导航API(Directions API)」并点击。
    • 选择「激活(ENABLE)」。当整个过程结束后,「导航API(Directions API)」会出现在「控制面板(Dashboard)」的API列表中。

导航请求

访问导航服务是异步的,因为Google Maps API需要在外部服务器调用。因此你需要传递一个callback来执行请求。注意导航服务可能返回不止一条导航线路,存储在一个包含多个独立的routes[]的阵列里。

为了应用Maps JavaScript API里的导航服务, 先创建一个DirectionsService类型的对象,并调用DirectionsService.route( )来初始化一个导航服务的请求,再传递含有输入字符和callback方法的DirectionsRequest对象来执行响应的回执。

DirectionsRequest对象含有以下信息:

```python
{
  origin: LatLng | String | google.maps.Place,
  destination: LatLng | String | google.maps.Place,
  travelMode: TravelMode,
  transitOptions: TransitOptions,
  drivingOptions: DrivingOptions,
  unitSystem: UnitSystem,
  waypoints[]: DirectionsWaypoint,
  optimizeWaypoints: Boolean,
  provideRouteAlternatives: Boolean,
  avoidFerries: Boolean,
  avoidHighways: Boolean,
  avoidTolls: Boolean,
  region: String
}
```
  • origin(必需)定义了测算导航服务的起始位置。输入格式可以是一个字符串string(比如”Chicago, IL”),一组经纬度Lat,Lng,或google.maps.Place对象。如果要使用google.maps.Place,需要指定一个place ID,一个请求字符串或一组经纬度数据。你可以通过Google Maps API的Geocoding,Place Search,和Place Autocomplete的服务获得place ID。Place Autocomplete and Directions是从Place Autocomplete获得Place ID的一个例子。
  • destination(必需)定义了测算导航服务的目的地位置。详细信息同上。
  • travelMode(必需)定义了出行的方式。这个字段该用什么值,下面会有详细的介绍。
  • transitOptions(可选)当travelMode是「公共交通(transit)」时需要设定这个值。
  • drivingOptions(可选)当travelMode是「自驾(driving)」时需要设定。
  • unitSystem(可选)定义了显示结果时的单位(公制或英制)。
  • waypoints[](可选)定义了DirectionWaypoint的阵列。不同的路径点会根据特定位置的不同而变化。一个路径点由以下的文本信息所具体化:
    • location指路径点的位置,由一组经纬度Lat,Lnggoogle.maps.Place对象,或一个被地理编码(geocode)的字符串表达。
    • stopover是一个布尔(boolean)值,表示路径上的一个停顿点,在此可以将一条路径分成两条路径。
  • optimizeWaypoints(可选)用一些经过更有效的顺序重新排列的路径点去优化waypoints路径。如果值是true,导航服务将在waypoint_order域中返回重新排序的waypoints
  • provideRouteAlternatives(可选)当设置成true时,说明导航服务或许提供多于一条可选路线作为响应。请注意计算多条可选路线可能会增加服务器响应的时间。这个对象只在不包含中间路径点的请求中适用。
  • avoidFerries(可选)当设置成true时,说明如果可能的话被计算出的路径应该避免渡船。
  • avoidHighways(可选)当设置成true时,说明如果可能的话被计算出的路径应该避开高速公路。
  • avoidTolls(可选)当设置成true时,说明如果可能的话被计算出的路径应该避开收费站。
  • region(可选)指区域代码,如ccTLD(「顶级域名」(top-level domain))中最后两个字符的值。

以下是一个DirectionsRequest的例子:

{
  origin: 'Chicago, IL',
  destination: 'Los Angeles, CA',
  waypoints: [
    {
      location: 'Joplin, MO',
      stopover: false
    },{
      location: 'Oklahoma City, OK',
      stopover: true
    }],
  provideRouteAlternatives: false,
  travelMode: 'DRIVING',
  drivingOptions: {
    departureTime: new Date(/* now, or future date */),
    trafficModel: 'pessimistic'
  },
  unitSystem: google.maps.UnitSystem.IMPERIAL
}

出行方式

当测算导航服务时,需要指定选择哪一种出行方式。以下是几种支持的方式:

  • DRIVING(默认)指利用路网信息提供标准自驾模式。
  • BICYCLING通过自行车路径和优选街道提供自行车导航模式。
  • TRANSIT通过公共交通路线提供导航服务。
  • WALKING通过行人路径和人行道提供步行导航服务。在步行导航服务中,有可能不能包括清晰的行人路径,所以将在DirectionResult中返回一些警告,如果你没有用默认的DirectionsRenderer,你需要将这些警告展现出来。

查看Google Maps coverage data中各国出行方式信息的覆盖情况。如果申请的区域没有相应的信息,将会返回DirectionsStatus=”ZERO_RESULTS

公共交通选项

导航请求的可选项会根据出行方式的不同而有所变化。当在公共交通导航时,avoidHighwaysavoidTollswaypoints[],和optimizeWaypoints这几个对象将被忽略掉。你可以通过TransitOptions指定一些特定的路径选项。

公共交通导航对时间很敏感。导航服务将仅返回未来时间点的结果。

TransitOptions对象包含以下参数:

{
  arrivalTime: Date,
  departureTime: Date,
  modes[]: TransitMode,
  routingPreference: TransitRoutePreference
}
  • arrivalTime(可选)可以指定到达目的地的时间(通过Date对象)。如果确定了到达时间,则出发时间将被忽略。
  • departureTime(可选)可以指定出发时间(通过Date对象)。如果确定了出发时间,则到达时间将被忽略。如果arrivalTimehdepartureTime都没有被指定时,默认的时间是现在(当前的时间)。
  • modes[](可选)是一个含有若干个TransitMode对象的阵列。每一个TransitMode指定了对应的方式:
    • BUS出行方式是公交车
    • RAIL出行方式是火车、轻轨、地铁和有轨电车。
    • SUBWAY出行方式是地铁。
    • TRAIN出行方式是火车。
    • TRAM出行方式是有轨电车和轻轨。
  • routingPreference(可选)可以帮助用户手动选择目标路径,而不是接受API提供的默认路径。
    • FEWER_TRANSFERS最小化换乘。
    • LESS_WALKING步行最少

以下是DirectionsRequest通过公共交通出行的一个例子:

{
  origin: 'Hoboken NJ',
  destination: 'Carroll Gardens, Brooklyn',
  travelMode: 'TRANSIT',
  transitOptions: {
    departureTime: new Date(1337675679473),
    modes: ['BUS'],
    routingPreference: 'FEWER_TRANSFERS'
  },
  unitSystem: google.maps.UnitSystem.IMPERIAL
}

自驾方式

可以利用DrivingOptions对象来指定自驾方式的路线。DrivingOptions对象包含以下域:

{
  departureTime: Date,
  trafficModel: TrafficModel
}
  • departureTime(必需)可以指定出发时间(通过Date对象)。这个时间必需设置成当前时间或未来的一个时间点而不能设在过去。(API将所有的时间转化为UTC来确保跨时区的时间正确性)。对于Google Maps APIs白金套餐用户来说,如果在请求中包含了departureTime,API将会返回当前时间交通拥堵情况,并返回耗时预测(duration_in_traffic)。如果不特别指定出发时间(即请求中不包括drivingOptions),返回的将是一个普通的,没有考虑交通拥堵情况的路线。为确保你的请求可以用到实时交通信息,可将departureTime设置成当前时间。但这样做Google将会收取较高的费用。点此了解更多Google Maps平台产品的收费情况。
  • trafficModel(可选)预估驾驶时间。这个值是基于历史平均值做出的预测,被duration_in_traffic作为返回值所引用。
    • bestguess(默认)表明返回的duration_in_traffic应为出行时间的最佳估计值(包括历史交通情况和实时交通情况)。departureTime离当前时间越近,实时的交通情况就越重要。
    • pessimistic表明返回的duration_in_traffic应该比实际出行时间略长,虽然通常情况下一些糟糕的交通状况会超出这个时间。
    • optimistic表明返回的duration_in_traffic应该比实际出行时间略短,虽然通常情况下一些良好的交通状况可能会比这个时间更快。

以下是自驾模式中DirectionsRequest的例子:

{
  origin: 'Chicago, IL',
  destination: 'Los Angeles, CA',
  travelMode: 'DRIVING',
  drivingOptions: {
    departureTime: new Date(Date.now() + N),  // for the time N milliseconds from now.
    trafficModel: 'optimistic'
  }
}

计量单位

默认情况下,导航系统会根据使用者所处的国家或地区的计量单位进行测算和展示。(注意:最基本的表达式是使用经纬度坐标而不是位置地址,默认情况下采用公制)举例来说,一条从”Chicago, IL”去往”Toronto, ONT”的路径将以英里作为单位,而反过来则将以公里作为单位。你可以在请求中使用UnitSystem的值来明确定义需要的计量单位。

  • UnitSystem.METRIC使用公制,以公里为单位
  • UnitSystem.Imperial使用英制,以英里为单位。

注意:计量单位的两种设置只是体现在给用户呈现的部分。在系统内部永远都是使用「米」来进行距离的测算。

域名差别

Google Maps API Directions Service服务返回的地址结果受到用户加载JavaScript引导程序的域名(国家或区域)的影响(因为绝大多数用户加载https://maps.google.com/的域名位置是美国)。举例来说,访问https://maps.google.com/(美国)和访问https://maps.google.es/(西班牙)搜索”San Francisco”将会得到不同的返回结果。

你也可以在导航服务中利用region参数设置指定区域的返回结果。这个参数携带一个区域代码,即IANA语言region subtag。在大多数情况下,这些标签会直接映射到ccTLD(顶级域名)中最后两位字母对应的地区,如”co.uk”中的”uk”。一些情况下,region标签也会支持ISO-3166-1编码,有时区别于ccTLD值,如用”GB”而不是””uk”代表”Great Britain”。

渲染结果

route()方法初始化一个DirectionsService导航请求需要传递一个回调函数。这个回调函数将在响应中返回一个DirectionsResultDirectionsStatus

导航请求的状态

DirectionsStatus可能返回以下的值:

  • OK表示响应包含有效的DirectionsResult
  • NOT_FOUND表示请求中出发地点、目的地或路径点中至少一个位置不能被地理编码。
  • ZERO_RESULTS表示在起始点和目的地之间没有搜索到路径。
  • MAX_WAYPOINTS_EXCEEDED表示在DirectionsRequest中有太多的DirectionsWaypoint域。
  • MAX_ROUTE_LENGTH_EXCEEDED表示请求的路线太长,不能被处理。当太多复杂的导航信息被返回时会出现这个错误。试着减少路径点、转弯或指示的数量。
  • INVALID_REQUEST表示DirectionsRequest无效。最常见的原因是请求中缺少出发地点或目的地之一,或在公共交通的请求中包含路径点。
  • REQUEST_DENIED表示网页不允许使用导航服务。
  • UNKNOWN_ERROR表示请求不能被处理,因为服务器的错误。建议过一阵再试试。

DirectionsResult的展示

DirectionsResult包含导航请求的结果,用户既可以自己处理,也可以将其传递给DirectionsRenderer对象,以便自动将结果展示在地图上。

使用DirectionsRenderer可以展示DirectionsResult,只需要执行如下几步:

  1. 创建一个DirectionsRenderer对象。
  2. 在渲染器上调用setMap()将指与地图绑定。
  3. 在渲染器上调用setDirections(),传递上述的DirectionsResult。因为渲染器是MVCObject,将会自动侦测出任何改动,并更新到相应的位置上。

下面的例子测算出在66号公路上两个位置的导航信息,起始点和目的地被标记为"start""end"DirectionsRenderer展示了两点之间的多条路径,以及起始点、目的地和路径点之间的标记。

function initMap() {
  var directionsService = new google.maps.DirectionsService();
  var directionsDisplay = new google.maps.DirectionsRenderer();
  var chicago = new google.maps.LatLng(41.850033, -87.6500523);
  var mapOptions = {
    zoom:7,
    center: chicago
  }
  var map = new google.maps.Map(document.getElementById('map'), mapOptions);
  directionsDisplay.setMap(map);
}

function calcRoute() {
  var start = document.getElementById('start').value;
  var end = document.getElementById('end').value;
  var request = {
    origin: start,
    destination: end,
    travelMode: 'DRIVING'
  };
  directionsService.route(request, function(result, status) {
    if (status == 'OK') {
      directionsDisplay.setDirections(result);
    }
  });
}

HTML的body:查看例子

Mode of Travel: 
 id="mode" onchange="calcRoute();">
   value="DRIVING">Driving
   value="WALKING">Walking
   value="BICYCLING">Bicycling
   value="TRANSIT">Transit

 

DirectionsRenderer不仅能处理展示任意标记点之间的路径,而且还能提供一系列导航步骤的文字说明。只需简单的在DirectionsRenderer上调用setPanel(),并将

 

传给它,就可以展现文字信息。

文字导航将根据浏览器的语言设置,或根据API JavaScript的language参数提供相应的语言(查看Localization获得更多的信息)。在公交导航的例子中,在公交站的时区信息上将展示时间。

接下来的例子是和上面展示的例子相同,但包含着一个

 

信息:

function initMap() {
  var directionsService = new google.maps.DirectionsService();
  var directionsDisplay = new google.maps.DirectionsRenderer();
  var chicago = new google.maps.LatLng(41.850033, -87.6500523);
  var mapOptions = {
    zoom:7,
    center: chicago
  }
  var map = new google.maps.Map(document.getElementById('map'), mapOptions);
  directionsDisplay.setMap(map);
  directionsDisplay.setPanel(document.getElementById('directionsPanel'));
}

function calcRoute() {
  var start = document.getElementById('start').value;
  var end = document.getElementById('end').value;
  var request = {
    origin:start,
    destination:end,
    travelMode: 'DRIVING'
  };
  directionsService.route(request, function(response, status) {
    if (status == 'OK') {
      directionsDisplay.setDirections(response);
    }
  });
}

HTML的body:显示例子

id=“map” style=float:left;width:70%; height:100%>

 


id=“directionsPanel” style=float:right;width:30%;height 100%>

 

DirectionsResult对象

当向DirectionsService发送一个导航请求时,你将收到一个含有状态码和结果的反馈,这就是DirectionsResult对象。DirectionsResult包含以下域:

  • geocoded_waypoints[]包含一个DirectionsGeocodedWaypoint对象的阵列,每一个对象都含有起始点、目的地和路径信息地理编码的详细信息。
  • routes[]包含一个DirectionsRoute对象的阵列。每一个路径表示在DirectionsRequest中从起始点到目的地获取一条通路。通常来说,对于任意请求只返回一条路径,除非请求的provideRouteAlternatives域被设置为true,在此条件下,将返回多条路径。

地理编码路径点

DirectionsGeocodedWaypoint包含起始点、目的地和路径信息地理编码的详细信息。它有如下的域:

  • geocoder_status表示从地理编码运算出得状态码。这个域或许包含如下值:
    • OK表示没有错误发生;地址成功被解析,而且至少返回一个地理编码。
    • ZERO_RESULTS表示地理编码是成功的,但没有结果被返回。或许地理编码被传入一个不存在的address
  • partial_match表示地理编码没有为原始请求返回一个明确的匹配值,虽然它可以匹配部分请求地址。建议检查原始请求是否存在拼写错误或/和不完整地址的情况。绝大多数情况的部分匹配发生在输入的街道地址在当地不存在。也有一些部分匹配发生在找到了两个或更多相同的位置信息。如”21 Henr St, Bristol, UK”将返回部分匹配,因为Henry Street和Henrietta Street都可以简写成Henr St。注意如果一个请求包含错误拼写,地址编码或许会推荐一个替代地址。当一条建议触发时,意味着产生了部分匹配。
  • place_id是一个位置唯一的代码,也可以用在其他Google API上。如你可以在Google Places API中使用place_id获取当地企业的地理物理信息,如电话号、营业时间、用户评价等。详见place ID overview
  • types[]表示返回结果类型的一组阵列。这个阵列包含返回结果中一组0值或更多的用来标记特征类型的标签。如一个”Chicago”的地理编码返回”locality”表示”Chicago”是一个城市,同样也返回”political”表示也是一个政治实体。

 

https://developers.google.com/maps/documentation/javascript/places#place_details

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

您正在使用您的 WordPress.com 账号评论。 注销 /  更改 )

Google photo

您正在使用您的 Google 账号评论。 注销 /  更改 )

Twitter picture

您正在使用您的 Twitter 账号评论。 注销 /  更改 )

Facebook photo

您正在使用您的 Facebook 账号评论。 注销 /  更改 )

Connecting to %s