Google Maps Directions API问题:获取带途经点及Leg信息的夏季短路线
解决Google Maps Directions API中stopover设置与夏季路线的冲突问题
我完全懂你现在的头疼点——既要拿到途经点对应的Leg分段信息,又得让API走那条只在夏季开放的短路线,这俩需求单独都能实现,放一起就卡壳了对吧?
咱们先理清楚问题根源:当你把stopover设为true时,API会把每个途经点当成必须停靠的站点,这时候它的优先级是确保能到达每个停靠点(哪怕绕路),直接忽略了departureTime指定的夏季开放路线;而stopover: false时,途经点只是引导路线的参考点,API会优先选最优的夏季短路线,但不会把路线拆分成对应的Leg段。
那怎么破?试试分两次请求API的方案,完美兼顾两个需求:
- 第一步:用
stopover: false请求一次,拿到正确的夏季短路线(包含途经点的实际路径); - 第二步:把这条路线的起点、途经点、终点拆成连续的点对,逐个请求API(每个请求都带上夏季的
departureTime),这样就能得到每一段的Leg信息; - 最后把这些Leg信息合并,就能得到你想要的完整结果。
下面是调整后的代码,你可以直接测试:
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> <style type="text/css"> html { height: 100% } body { height: 100%; margin: 0px; padding: 0px } </style> <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3"></script> <script type="text/javascript"> var directionDisplay; var directionsService = new google.maps.DirectionsService(); var map; var wptruefalse; function initialize() { directionsDisplay = new google.maps.DirectionsRenderer(); var myOptions = { zoom: 6, mapTypeId: google.maps.MapTypeId.ROADMAP }; map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); directionsDisplay.setMap(map); calcRoute(); } function calcRoute() { var first = new google.maps.LatLng(61.84448683734486, 8.85223388671875); var second = new google.maps.LatLng(61.75298123367897, 9.078826904296875); var start = new google.maps.LatLng(61.484039,7.645798); var end = new google.maps.LatLng(61.944118091023746,7.97882080078125); // 第一步:先获取正确的夏季短路线(stopover=false) var initialRequest = { origin: start, destination: end, waypoints: [{location: first, stopover: false}, {location: second, stopover: false}], optimizeWaypoints: true, travelMode: google.maps.DirectionsTravelMode.DRIVING, drivingOptions: { departureTime: new Date("08/08/2018") }, }; directionsService.route(initialRequest, function (initialResponse, status) { if (status == google.maps.DirectionsStatus.OK) { // 提取路线上的关键节点:起点 + 优化后的途经点 + 终点 var route = initialResponse.routes[0]; var waypointLocations = []; waypointLocations.push(route.legs[0].start_location); // 提取途经点的实际位置 route.waypoint_order.forEach(function(idx) { waypointLocations.push(initialRequest.waypoints[idx].location); }); waypointLocations.push(route.legs[0].end_location); // 第二步:分段请求获取每一段的Leg信息 var allLegs = []; var currentIndex = 0; function fetchNextLeg() { if (currentIndex >= waypointLocations.length - 1) { // 所有Leg获取完成,合并并显示 displayCombinedRoute(allLegs); return; } var segmentRequest = { origin: waypointLocations[currentIndex], destination: waypointLocations[currentIndex + 1], travelMode: google.maps.DirectionsTravelMode.DRIVING, drivingOptions: { departureTime: new Date("08/08/2018") }, }; directionsService.route(segmentRequest, function(segResponse, segStatus) { if (segStatus == google.maps.DirectionsStatus.OK) { allLegs.push(segResponse.routes[0].legs[0]); currentIndex++; fetchNextLeg(); } else { alert("Segment request failed: " + segStatus); } }); } fetchNextLeg(); } else { alert("Initial directions response failed: " + status); } }); } function displayCombinedRoute(allLegs) { // 构造合并后的路线对象,适配DirectionsRenderer var combinedRoute = { routes: [{ legs: allLegs, overview_path: [], bounds: new google.maps.LatLngBounds() }] }; // 合并overview_path和bounds allLegs.forEach(function(leg) { leg.steps.forEach(function(step) { combinedRoute.routes[0].overview_path = combinedRoute.routes[0].overview_path.concat(step.path); }); combinedRoute.routes[0].bounds.extend(leg.start_location); combinedRoute.routes[0].bounds.extend(leg.end_location); }); // 显示路线 directionsDisplay.setDirections(combinedRoute); // 显示Leg信息 var summaryPanel = document.getElementById("directions_panel"); summaryPanel.innerHTML = ""; for (var i = 0; i < allLegs.length; i++) { var routeSegment = i + 1; summaryPanel.innerHTML += "<b>Route Segment: " + routeSegment + "</b><br />"; summaryPanel.innerHTML += allLegs[i].start_address + " to "; summaryPanel.innerHTML += allLegs[i].end_address + "<br />"; summaryPanel.innerHTML += allLegs[i].distance.text + "<br /><br />"; } } function doClick(myRadio) { // 这里我们固定用分阶段方案,不管stopover选择,因为要兼顾两个需求 calcRoute(); } </script> </head> <body onload="initialize()"> <div id="map_canvas" style="float:left;width:70%;height:100%;"></div> <div id="control_panel" style="float:right;width:30%;text-align:left;padding-top:20px"> API Key is needed to test properly <form> <input type="radio" name="wpradio" onclick="doClick(this);" value="true" checked> True <input type="radio" name="wpradio" onclick="doClick(this);" value="false"> False </form> <div id="directions_panel" style="margin:20px;background-color:#FFEE77;"></div> </div> </body> </html>
这个方案的核心是先用stopover: false锁定正确的夏季路线,再把路线拆分成小段单独请求,这样每一段都能返回对应的Leg信息,同时保证走的是夏季开放的道路。
内容的提问来源于stack exchange,提问作者Lesley Persyn
相关产品推荐
相关产品推荐

