以编程方式更改google.maps.DirectionsResult

时间:2015-06-02 19:09:24

标签: javascript google-maps google-maps-api-3

使用google.maps.DirectionsService类时,将一些航点传递给其请求,将获得一个google.maps.DirectionsResult对象,该对象可以使用google.maps.DirectionsRenderer类在地图上显示。

默认情况下,指定的航点将显示为标记为A,B,C等标记......

如果DirectionsRenderer配置为可拖动,则拖动这些航点标记将依次触发DirectionsRenderer上的directions_changed,填充其dragResult属性,并最终更改基础路线。如果要显示,此更改将传播到每个相关对象,包括指令面板。

上述行为is shown in this example

我无法弄清楚如何以编程方式模拟此拖动操作。我已经尝试操纵DirectionsResult对象并调用DirectionsRenderer对象的setDirections方法,但这种操作通常会导致路径不一致。

例如,有时我的一个航点落在死胡同上。

Waypoint on dead end

获取我的DirectionsResult对象后,我会迭代它的每一条腿。如果之间的角度

  1. 给定腿的最后一步和
  2. 下一站的第一步
  3. 接近180°意味着我必须回头,所以我想把那个路点改成下一个合适的位置。我是这样做的:

    var computeHeading=function(location1,location2) {
        return google.maps.geometry.spherical.computeHeading(location1,location2);
    };
    
    var legsArray = DirectionsResult.routes[0].legs;
    for (var legIndex = 0; legIndex < legsArray.length - 1; legIndex++) {
        // Current leg
        var DirectionsLeg = legsArray[legIndex];
    
        // Last Step of current Leg
        var lastDirectionsStep = DirectionsLeg.steps.slice(-1)[0];
    
        // Next Leg
        var nextDirectionsLeg = legsArray[legIndex + 1];
    
        // First step of Next Leg
        var nextDirectionsStep = nextDirectionsLeg.steps[0];
    
        var lastHeading = computeHeading(lastDirectionsStep.start_location, lastDirectionsStep.end_location);
        var nextHeading = computeHeading(nextDirectionsStep.start_location, nextDirectionsStep.end_location);
        var theAngle = Math.abs(nextHeading-lastHeading);
    
        // Arbitrary threshold. If the angle is over 170 it's a deadend
        if(theAngle>170) {
            DirectionsLeg.steps.pop();
            DirectionsLeg.end_location = DirectionsLeg.steps.slice(-1)[0].end_location;
    
            nextDirectionsLeg.steps = nextDirectionsLeg.steps.slice(1);
            nextDirectionsLeg.start_location =nextDirectionsLeg.steps[0].start_location;
        }
    }
    

    事实证明,腿0的倒数第二个位置并不总是与第1腿的第二个位置相匹配,所以我在路线腿之间产生了不必要的间隙。手动拖动航点标记时不会发生这种情况:它设法保持路线连续性。

1 个答案:

答案 0 :(得分:0)

事实证明,拖动标记会触发一次或多次调用Directions API,这是我为了经济而试图避免的。所以我认为,在修剪原始DirectionsResult的腿之后,我应该重新定义航点并申请一条新航线。

var optimizeRoute=function(DirectionsResult) {

    var computeHeading=function(location1,location2) {
        return google.maps.geometry.spherical.computeHeading(location1,location2);
    };

    var legsArray = DirectionsResult.routes[0].legs;
    for (var legIndex = 0; legIndex < legsArray.length - 1; legIndex++) {
        // Current leg
        var DirectionsLeg = legsArray[legIndex];

        // Last Step of current Leg
        var lastDirectionsStep = DirectionsLeg.steps.slice(-1)[0];

        // Next Leg
        var nextDirectionsLeg = legsArray[legIndex + 1];

        // First step of Next Leg
        var nextDirectionsStep = nextDirectionsLeg.steps[0];

        var lastHeading = computeHeading(lastDirectionsStep.start_location, lastDirectionsStep.end_location);
        var nextHeading = computeHeading(nextDirectionsStep.start_location, nextDirectionsStep.end_location);
        var theAngle = Math.abs(nextHeading-lastHeading);

        // Arbitrary threshold. If the angle is over 170 it's a deadend
        if(theAngle>170 && theAngle<190) {
            DirectionsLeg.steps.pop();
            DirectionsLeg.end_location = DirectionsLeg.steps.slice(-1)[0].end_location;
            DirectionsResult.request.waypoints[legIndex].location = DirectionsLeg.end_location;
            DirectionsResult.needsReroute = true;
        }
    }

    return DirectionsResult;
}

之后,如果&#34;优化&#34; DirectionsResult拥有物业&#34; needReroute&#34;设置为true,我对google.maps.DirectionsService类进行了新的调用,这次使用第一个DirectionsResult.request作为修改后的请求。

所以,让我们说我有这个函数接受一个请求并回调一个DirectionsResult:

var getRoute=function(myRequest,callback) {

   var DirectionsService=new google.maps.DirectionsService();

   DirectionsService.route(myRequest, function(DirectionsResult, status) {

    if(status === google.maps.DirectionsStatus.OK) {

         var optimizedDirectionsResult=optimizeRoute(DirectionsResult);

         if(optimizedDirectionsResult.needsReroute) {
             getRoute(optimizedDirectionsResult.request, callback);
         } else {
             callback(optimizedDirectionsResult);
         }

     } else {
       console.warn('failed',status);
       callback(null);
     }

   });

};