2013-04-23 6 views
0

나는 포인트 배열을 받아들이고 하나의 경로로 맵에 표시하는 함수를 만들고 있습니다. 내 배열이 항상 점 (보통 100 개 이상)의 엄청난 금액을 포함 반복적으로 단지 완료 이전 요청을 기다릴 밖으로 동결지도로 함수를 호출에렌더링 방향에서 Google지도를 중지하는 방법?

function __RenderRoute(map, points, lineColor, DrawResult, i, callback, waitTime) { 
    var tmpPoints = points.slice(i, i + 9); 
    if (tmpPoints.length > 1) { 
     var request = { 
      origin: tmpPoints.shift().location, 
      destination: tmpPoints.pop().location, 
      waypoints: tmpPoints, 
      travelMode: google.maps.TravelMode.DRIVING 
     }; 
    } 
    var directionsService = new google.maps.DirectionsService(); 
    directionsService.route(request, function (result, status) { 
     if (status == google.maps.DirectionsStatus.OK) { 
      var directionsDisplay = new google.maps.DirectionsRenderer({ 
       draggable: false, 
       markerOptions: { 
        visible: false 
       }, 
       polylineOptions: { 
        clickable: true, 
        strokeColor: lineColor, 
        strokeOpacity: .6, 
        strokeWeight: 6, 
        zIndex: 5 
       }, 
       preserveViewport: true 
      }); 
      directionsDisplay.setMap(map); 
      directionsDisplay.setDirections(result); 
      DrawResult.directionDisplays.push(directionsDisplay); 
     } else { 
      console.log(status); 
      console.log("Wait " + waitTime + " miliseconds."); 
      setTimeout(function() { __RenderRoute(map, points, lineColor, DrawResult, i, callback, waitTime * 2) }, waitTime); 
      return; 
     } 
     DrawResult.directionResults.push(result); 
     if (i + 9 < points.length) { 
      __RenderRoute(map, points, lineColor, DrawResult, i + 8, callback, 350); 
     } else { 
      if (callback != null) { 
       callback(); 
      } 
      DrawResult.completed = true; 
     } 
    }); 
} 

그러나, 그것은 어렵습니다. 어쨌든 Google지도를 렌더링 경로에서 멈추거나 다시 호출 할 때 대기하는 동안 콜백 자체에서 기능을 중지 할 수 있습니까?

+0

이것이 답이라고 생각하지 않지만 'if (tmpPoints.length> 1)'테스트에 실패하면 어떻게됩니까? 'request'는 정의되지 않고'directionsService.route (request, function (result, status) ...'는 외부 범위에서'request'를 받거나 에러를 던질 것입니다 –

+0

사실 tmpPoints.length는 항상> 1입니다. 만약 (tmpPoints.length> 1) 의미가 없다면, 아직 제거하지 않았기 때문에 여전히 그 이유가 있습니다. – vCube

+0

'tmpPoints.length'는 오늘과 내일 그리고 그 다음날보다 클 수도 있지만 항상 * 1보다 커야합니까? [방어 프로그래밍] (http://en.wikipedia.org/wiki/Defensive_programming). –

답변

0

Google에서 8 개의 웨이 포인트 제한을 극도로 간단히 극복 할 수 있는지 여부는 아직 확실하지 않지만 여기에 나와 있습니다.

I가 볼 수있는 __RenderRoute()를 수정 :

  • 모든 directionsService.route 세그먼트의 데이터를 포함하는 합성 경로 객체를 만드는 등 ... 전체 경로
  • 대해 한 번 호출 될 수 있다는 모든 재귀가 완료되거나 의미있는 오류 메시지와 함께 거부 될 때 해결되는 약속을 반환합니다.

주요 기능 __RenderRoute() : 적합한 범위

function __RenderRoute(points, i, waitTime, dfrd, errorObj) {//<<<<< Now called with a reduced number of parameters 
    dfrd = dfrd || $.Deferred(); 
    errorObj = errorObj || { 
     count: 0, 
     threshold: 5//adjust as necessary 
    }; 
    var tmpPoints = points.slice(i, i + 9); 
    if (tmpPoints.length < 2) { 
     if (i == 0) {//top level call 
      dfrd.reject("Not enough points"); 
      return dfrd.promise(); 
     } 
     else { return; } 
    } 
    var request = { 
     origin: tmpPoints.shift().location, 
     destination: tmpPoints.pop().location, 
     waypoints: tmpPoints, 
     travelMode: google.maps.TravelMode.DRIVING 
    }; 
    var route = new RouteResult();//Custom object that allows successive directionsService.route results to be componded into a single route. 
    var directionsService = new google.maps.DirectionsService(); 
    directionsService.route(request, function (result, status) { 
     if (status == google.maps.DirectionsStatus.OK) { 
      route.add(result);//Hopefully magic happens here. 
      if(i + 9 < points.length) { 
       __RenderRoute(points, i+8, 350, dfrd, errorObj); 
      } else { 
       dfrd.resolve(route);//<<<<< Resolve the jQuery Deferred object 
      } 
     } else { 
      console.log("google.maps.DirectionsService status = " + status); 
      if(++errorObj.count < errorObj.threshold) { 
       console.log("Wait " + waitTime + " miliseconds."); 
       setTimeout(function() { 
        __RenderRoute(points, i, waitTime*2, dfrd, errorObj); 
       }, waitTime); 
      } 
      else { 
       dfrd.reject('Error threshold (' + errorObj.threshold + ') exceeded'); //Reject the jQuery Deferred object 
      } 
     } 
    }); 
    return dfrd; 
} 

directionsDisplay를 정의 적합한 범위

//I think a DirectionsRenderer is reusable. If so `directionsDisplay` needs to be constructed only once as below. If not, then move this block inside foo(). 
var directionsDisplay = new google.maps.DirectionsRenderer({ 
    draggable: false, 
    markerOptions: { 
     visible: false 
    }, 
    polylineOptions: { 
     clickable: true, 
     strokeColor: '#99F',//adjust as desired 
     strokeOpacity: .6, 
     strokeWeight: 6, 
     zIndex: 5 
    }, 
    preserveViewport: true 
}); 
directionsDisplay.setMap(map);//Assumed to be defined elsewhere 

RouteResult() 정의

이어서
/* 
* RouteResult is a utility class that will (hopefully) 
* allow several routes to be compounded into one. 
* Based on information here : 
* - https://developers.google.com/maps/documentation/javascript/directions 
* - 
* This is experimental and untested. 
*/ 
function RouteResult() { 
    var r = { 
     legs: [], 
     waypoint_order: [], 
     overview_path: [], 
     copyrights: [], 
     warnings: [], 
     bounds : new google.maps.LatLngBounds()//initially empty LatLngBounds obj 
    }; 
    this.add = function (result) { 
     r.legs = r.legs.concat(result.legs); 
     r.waypoint_order = r.waypoint_order.concat(result.waypoint_order); 
     r.overview_path = r.overview_path.concat(result.overview_path); 
     r.copyrights = r.copyrights.concat(result.copyrights); 
     r.warnings = r.warnings.concat(result.warnings); 

     r.bounds = r.bounds.union(result.bounds);//??? 
     //or possibly just 
     //r.bounds.union(result.bounds);//??? 
    }; 
    this.get = function() { return r; }; 
} 

, 다음과 같이 __RenderRoute() 전화 :

//foo() is an assumed function from which __RenderRoute() is called. 
function foo() { 
    ... 
    //__RenderRoute returns a Promise, allowing `.done()` and `.fail()` to be chained. 
    __RenderRoute(points, 0, 350).done(function(route) { 
     directionsDisplay.setDirections(route.get());//route is a custom object. .get() returns the actuual route. 
     //You can safely call __RenderRoute() again here, eg. with `setTimeout(foo, delay)`. 
    }).fail(function(errMessage) { 
     console.log(errMessage); 
    }); 
    ... 
} 
  • 코드에 주석을 참조하십시오.
  • 테스트되지 않았으므로 아마도 디버깅이 필요할 것입니다.
  • 작동하지 않으면 어쩌면 아이디어를 얻을 수 있습니다.
관련 문제