2014-09-28 146 views
1

首先,我想说我不太经验Google Maps Javascript API v3(我唯一的经验是最近3天)。我已成功地显示与标记列表的地图,并使用DirectionsService将它们连接起来,但有时我的名单是相当大的,我得到了以下错误:请求实体太大 - 谷歌地图方向错误413

Failed to load resource: the server responded with a status of 413 (Request Entity Too Large) 

这是我的代码:

// List of all locations for device 
var locations = []; 
// example: locations = [ 
//  {datetime: '2014/09/28 20:20', location: '41.99999 21.99999 30.0'}, 
//  ... {...} ... may be more than 200 entries for locations 
//  {datetime: '2014/09/28 20:25', location: '41.99999 21.99999 30.0'} 
// ] 

var map; 
var markers = []; 
var bounds = new google.maps.LatLngBounds(); 
var pathPoints = []; 
var infoWindow = new google.maps.InfoWindow(); 
var accuracy = new google.maps.Circle({ 
    fillColor: '#ff4080', 
    fillOpacity: 0.5, 
    strokeOpacity: 0, 
    zIndex: 0 
}); 
var path = new google.maps.Polyline(polyOptions); 
var geocoder; 
var directionsService = new google.maps.DirectionsService(); 
var directionsDisplay; 
var polyOptions = { 
    geodesic: true, 
    strokeColor: '#28b8b8', 
    strokeOpacity: 1.0, 
    strokeWeight: 8, 
    zIndex: 1 
} 
function showInfoWindow(marker, datetime, acc){ 
    geocoder = new google.maps.Geocoder(); 
    geocoder.geocode({ 
     'latLng': marker.getPosition() 
    }, function(results, status) { 
     if (status == google.maps.GeocoderStatus.OK) { 
      if (results[1]) { 
       infoWindow.close(); 
       var date = datetime.split(" ")[0]; 
       var time = datetime.split(" ")[1]; 
       var content = '<div class="infowindow">' 
         + results[1].formatted_address.trim() + '<br />' 
         + 'Date: ' + date + '<br />' 
         + 'Time: ' + time + '<br />' 
         + 'Accuracy: ' + acc + 'm' 
         + '</div>'; 
       infoWindow.setContent(content); 
       infoWindow.open(map, marker); 
       accuracy.setMap(null); 
       accuracy.setMap(map); 
       accuracy.setCenter(marker.getPosition()); 
       accuracy.setRadius(acc/1.6); 
      } else { 
       // alert('No results found'); 
      } 
     } else { 
      alert('Geocoder failed due to: ' + status); 
     } 
    }); 
} 
function addMultiMarker(latLng, num, datetime, acc){ 
    // Create marker at provided location 
    var marker = new google.maps.Marker({ 
     position: latLng, 
     map: map, 
     icon: image_circle, 
     title: 'Location #' + num, 
     zIndex: num + 1 
    }); 
    // On marker click center it inside map and show infoWindow 
    google.maps.event.addListener(marker, 'click', function() { 
     map.panTo(marker.getPosition()); 
     showInfoWindow(marker, datetime, acc); 
    }); 
    return marker; 
} 
function showRoute() { 
    var rendererOptions = { 
     draggable: false, 
     hideRouteList: true, 
     suppressMarkers: true, 
     infoWindow: infoWindow, 
     polylineOptions: polyOptions, 
     map: map 
    }; 
    directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions); 
    var len = markers.length; 
    var start = markers[0].getPosition(); 
    var end = markers[len - 1].getPosition(); 
    new google.maps.event.trigger(markers[len - 1], 'click'); 
    var wayPts = []; 
    for(var i = 1; i < len - 1; i++){ 
     wayPts.push({ 
      location: markers[i].getPosition(), 
      stopover: true 
     }); 
    } 
    var request = { 
     origin: start, 
     destination: end, 
     waypoints: wayPts, 
     optimizeWaypoints: true, 
     travelMode: google.maps.TravelMode.DRIVING 
    }; 
    directionsService.route(request, function(response, status) { 
     if (status == google.maps.DirectionsStatus.OK) { 
      directionsDisplay.setDirections(response); 
     } 
    }); 
} 
function showMapPeriod(periodStart, periodEnd){ 
    // Simple map options 
    var mapOptions = { 
     zoom: 15, 
     center: new google.maps.LatLng(41, 21), 
     mapTypeId : google.maps.MapTypeId.ROADMAP, 
     mapTypeControl: true, 
     mapTypeControlOptions: { 
      style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR, 
      position: google.maps.ControlPosition.TOP_RIGHT 
     }, 
     zoomControl: true, 
     zoomControlOptions: { 
      style: google.maps.ZoomControlStyle.LARGE, 
      position: google.maps.ControlPosition.LEFT_CENTER 
     }, 
     panControl: false, 
     streetViewControl: false 
    }; 
    $("#map").html(""); 
    // Create and show map 
    openMapContainer(); // just a function that shows the map <div> element 
    map = new google.maps.Map(document.getElementById('map'), mapOptions); 
    // Create and display markers 
    bounds = new google.maps.LatLngBounds(); 
    markers = []; 
    var len = 0; 
    for(var i = periodStart; i <= periodEnd; i++, len++){ 
     var loc_vals = locations[i].location.trim().split(" "); 
     var lat = parseFloat(loc_vals[0]); 
     var lng = parseFloat(loc_vals[1]); 
     var acc = parseFloat(loc_vals[2]); 
     // Create marker at provided location 
     var datetime = locations[i].datetime; 
     var latLng = new google.maps.LatLng(lat, lng); 
     markers[len] = addMultiMarker(latLng, len+1, datetime, acc); 
     bounds.extend(latLng); 
    } 
    showRoute(); 
    map.fitBounds(bounds); 
} 

那么我的代码部分工作,如果有人可以帮助我消除这个问题,我将非常感激。为了更好地解释它,我需要某种解决方案来请求Directions提供很多(200+)路标或某种方式来连接路段中的位置(我并不真正需要路线,但我不想连接地理位置简单Polyline)。

编辑:Here我已经提供了一个简单的演示,看到在line 15只是取消注释的问题。

+0

请提供一个展示此问题的示例。 – geocodezip 2014-09-28 22:40:55

+0

如何更改这些以展示此问题? – geocodezip 2014-09-29 03:57:20

+0

在这里[小提琴](http://jsfiddle.net/o3zqhsaz/6/),你可以看到点没有连接 – kiko283 2014-09-30 06:55:10

回答

5

因为没有人能够帮助我解决我的问题,我必须自己解决它。我正在回答我自己的问题,因为这对许多人来说似乎都是一个问题,并且在网络上解释不够,所以这可能会帮助有类似问题的开发人员。

无论如何,让我们来谈谈。该错误是因为谷歌限制抛出OxyDesign建议的,错误是:

  • google.maps.DirectionsResult.MAX_WAYPOINTS_EXCEEDED - 这是因为我发送的请求与起源目的地和超过8(谷歌限制)航点

,我很容易解决(I只是分裂与作为下一个的所述第一点的一个请求的最后一个点的10个点的块的阵列),但是然后我得到另一个错误:

  • google.maps.DirectionsResult.OVER_QUERY_LIMIT - 这是因为我试图每秒发送超过10次(再次限制Google)请求。

这需要多一点实验,搜索和测试来解决,但我解决了它。

现在,这里是为我工作的代码(至少在发布的时间,直到谷歌改变的东西):

// list of randomly generated locations (max 288) 
var locations = []; 
for(var i=0; i<288; i++){ 
    locations[i] = { 
     datetime: '2014/10/01 12:10', 
     location: (51 + Math.random()) + 
     ' ' + (-0.5 + Math.random()) + ' 30.0' 
    }; 
} 
// Marker images 
var image_pin = new google.maps.MarkerImage(
    'http://stedkomerc.com.mk/gpslocator/images/mPin.svg', 
    new google.maps.Size(25, 41), // size 
    new google.maps.Point(0, 0), // origin, top-left corner 
    new google.maps.Point(12, 40) // anchor 
); 
var image_circle = new google.maps.MarkerImage(
    'http://stedkomerc.com.mk/gpslocator/images/mCircle.svg', 
    new google.maps.Size(19, 19), // size 
    new google.maps.Point(0, 0), // origin, top-left corner 
    new google.maps.Point(9, 9) // anchor 
); 
// Variables 
var map; 
var bounds = new google.maps.LatLngBounds(); 
var markers = []; 
var pathPoints = []; 
var geocoder; 
var infoWindow = new google.maps.InfoWindow(); 
var accuracy = new google.maps.Circle({ 
    fillColor: '#ff4080', 
    fillOpacity: 0.4, 
    strokeOpacity: 0, 
    zIndex: 0 
}); 
var polyOptions = { 
    geodesic: true, 
    strokeColor: '#28b8b8', 
    strokeOpacity: 1.0, 
    strokeWeight: 8, 
    zIndex: 1 
}; 
var path = new google.maps.Polyline(polyOptions); 
var directionsService = new google.maps.DirectionsService(); 
var directions = []; 
var rendererOptions = { 
    draggable: false, 
    hideRouteList: true, 
    suppressMarkers: true, 
    preserveViewport: true, 
    infoWindow: infoWindow, 
    polylineOptions: polyOptions 
}; 
var requests = []; 
var MAX_POINTS_PER_REQUEST = 10; // 8*waypts Google limit + start + end 
var MAX_REQUESTS_PER_SECOND = 10; // Google limit 
// functions 
function showInfoWindow(marker, datetime, acc){ 
    geocoder = new google.maps.Geocoder(); 
    geocoder.geocode({ 
     'latLng': marker.getPosition() 
    }, function(results, status) { 
     if (status == google.maps.GeocoderStatus.OK) { 
      if (results[1]) { 
       infoWindow.close(); 
       var date = datetime.split(" ")[0]; 
       var time = datetime.split(" ")[1]; 
       var content = '<div class="infowindow">' + 
        results[1].formatted_address.trim() + '<br />' + 
        'Date: ' + date + '<br />' + 
        'Time: ' + time + '<br />' + 
        'Accuracy: ' + acc + 'm' + 
        '</div>'; 
       infoWindow.setContent(content); 
       infoWindow.open(map, marker); 
       accuracy.setMap(null); 
       accuracy.setMap(map); 
       accuracy.setCenter(marker.getPosition()); 
       accuracy.setRadius(acc); 
      } 
     } else { 
      console.log('Geocoder failed due to: ' + status); 
     } 
    }); 
} 
function addMultiMarker(latLng, num, datetime, acc){ 
    // Create marker at provided location 
    var marker = new google.maps.Marker({ 
     position: latLng, 
     map: map, 
     icon: image_circle, 
     title: 'Location #' + num, 
     zIndex: num + 1 
    }); 
    // On marker click center it inside map and show infoWindow 
    google.maps.event.addListener(marker, 'click', function() { 
     //map.panTo(marker.getPosition()); 
     showInfoWindow(marker, datetime, acc); 
    }); 
    return marker; 
} 
function connectMarkersPolyline(mrkrs){ 
    path.setMap(map); 
    pathPoints = path.getPath(); 
    len = mrkrs.length; 
    for(var i = 0; i < len; i++){ 
     pathPoints.push(mrkrs[i].getPosition()); 
    } 
} 
function connectMarkersRoute(mrkrs, part, maxParts){ 
    var directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions); 
    directionsDisplay.setMap(map); 
    var len = mrkrs.length; 
    var start = mrkrs[0].getPosition(); 
    var end = mrkrs[len - 1].getPosition(); 
    var wayPts = []; 
    for(var i = 1; i < len - 1; i++){ 
     wayPts.push({ 
      location: mrkrs[i].getPosition(), 
      stopover: true 
     }); 
    } 
    var request = { 
     origin: start, 
     destination: end, 
     waypoints: wayPts, 
     optimizeWaypoints: false, 
     travelMode: google.maps.TravelMode.DRIVING, 
     unitSystem: google.maps.UnitSystem.METRIC 
    }; 
    directionsService.route(request, function(response, status) { 
     if (status == google.maps.DirectionsStatus.OK) { 
      // request status OK, display route 
      directionsDisplay.setDirections(response); 
      // save it in array in case we want to remove it later 
      directions.push(directionsDisplay); 
      // if not last chunk, send next chunk after 100ms 
      // 1 request per 100ms => 10 requests per 1s 
      if(part+1 < maxParts) 
       setTimeout(connectMarkersRoute(requests[part+1], part+1, maxParts), 100); 
      else showLastMarker(); 
     } else if (status == google.maps.DirectionsStatus.OVER_QUERY_LIMIT) { 
      // if we get error, send same request after bigger delay (120ms) 
      setTimeout(connectMarkersRoute(requests[part], part, maxParts), 120); 
     } else { 
      // if all fails, connect with simple polyline 
      console.log('Directions failed due to: ' + status); 
      connectMarkersPolyline(mrkrs); 
     } 
    }); 
} 
function connectMarkers(markers){ 
    path.setMap(null); 
    path.setPath([]); 
    directions = []; 
    requests = []; 
    var len = markers.length; 
    console.log('connecting ' + len + ' markers'); 
    var i, j; 
    // split markers array into chunks of 10 (start + waypts + end) 
    for(i=0; i<len; i+=MAX_POINTS_PER_REQUEST-1){ 
     if(i<len-1) 
      requests.push(markers.slice(i, i+MAX_POINTS_PER_REQUEST)); 
    } 
    // send first chunk to connectMarkersRoute() 
    connectMarkersRoute(requests[0], 0, requests.length); 
} 
function showMapPeriod(periodStart, periodEnd){ 
    // Map options 
    var mapOptions = { 
     zoom: 16, 
     center: new google.maps.LatLng(41.995922, 21.431465), 
     mapTypeId : google.maps.MapTypeId.ROADMAP, 
     mapTypeControl: true, 
     mapTypeControlOptions: { 
      style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR, 
      position: google.maps.ControlPosition.TOP_RIGHT 
     }, 
     zoomControl: true, 
     zoomControlOptions: { 
      style: google.maps.ZoomControlStyle.LARGE, 
      position: google.maps.ControlPosition.LEFT_CENTER 
     }, 
     panControl: false, 
     streetViewControl: false 
    }; 
    $("#map").html(""); 
    //openMapContainer(); 
    // Create and show map 
    map = new google.maps.Map(document.getElementById('map'), mapOptions); 
    // Create and display markers 
    bounds = new google.maps.LatLngBounds(); 
    markers = []; 
    var len = 0; 
    for(var i = periodStart; i <= periodEnd; i++, len++){ 
     var loc_vals = locations[i].location.trim().split(" "); 
     var lat = parseFloat(loc_vals[0]); 
     var lng = parseFloat(loc_vals[1]); 
     var acc = parseFloat(loc_vals[2]); 
     // Create marker at provided location 
     var datetime = locations[i].datetime; 
     var latLng = new google.maps.LatLng(lat, lng); 
     markers[len] = addMultiMarker(latLng, len+1, datetime, acc); 
     bounds.extend(latLng); 
    } 
    connectMarkers(markers); 
    map.fitBounds(bounds); 
    if(map.getZoom() > 16) map.setZoom(16); 
} 
function showLastMarker(){ 
    new google.maps.event.trigger(markers[markers.length - 1], 'click'); 
} 
// show map 
showMapPeriod(1, 280); 
// -------- 

正如你所看到的,我所做的唯一真正的变化是showRoute()功能变为connectMarkers()与处理两种错误的connectMarkersRoute()connectMarkersPolyline()相结合。可以看到工作示例here。加载所有路由块需要一点时间,但至少可以工作。希望这可以帮助别人。

请注意,Google的每日限制还有2500 Directions个请求,所以要小心。话虽如此,这个答案甚至可以用于比200个地点更大的请求,我已经在1250个地点进行了测试,结果很有效。

2

似乎有此服务Gmaps Waypoints(或,我试着和它的工作,直到39,然后40没有),有没有办法做到这一点的另一种方式,除了与折线的限制,但你不希望它,所以我认为没有可行的解决方案...

+0

非常感谢您的信息,我读了有关的限制,现在我正在寻找某种解决方法 – kiko283 2014-09-28 23:40:47

+0

好的,祝你好运!而且,如果您找到解决方案,请在此处添加。谢谢 – OxyDesign 2014-09-29 09:19:50

+0

我发现了一个解决方案,你可以在我的答案中看到它[下面](http://stackoverflow.com/questions/26088925/request-entity-too-large-google-map-directions-error-413/#26153175 )。 – kiko283 2014-10-02 09:55:07

相关问题