admin管理员组文章数量:1403452
First, I want to say I'm not too experienced with Google Maps Javascript API v3
(my only experience are these last 3 days). I have managed to display a map with a list of markers and connect them using DirectionsService
, but sometimes my list is pretty large and I get the following error:
Failed to load resource: the server responded with a status of 413 (Request Entity Too Large)
This is my code:
// 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);
}
Well my code works partially and if someone can help me to eliminate the problem I would very much appreciate it. To explain it better, I need some kind of solution to request Directions
with a lot (200+) waypoints or some way to connect the locations through the roads (I don't really need the directions, but I don't want to connect the locations with a simple Polyline
).
EDIT: Here I have provided a simple demo, to see the problem just unment at line 15
.
First, I want to say I'm not too experienced with Google Maps Javascript API v3
(my only experience are these last 3 days). I have managed to display a map with a list of markers and connect them using DirectionsService
, but sometimes my list is pretty large and I get the following error:
Failed to load resource: the server responded with a status of 413 (Request Entity Too Large)
This is my code:
// 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);
}
Well my code works partially and if someone can help me to eliminate the problem I would very much appreciate it. To explain it better, I need some kind of solution to request Directions
with a lot (200+) waypoints or some way to connect the locations through the roads (I don't really need the directions, but I don't want to connect the locations with a simple Polyline
).
EDIT: Here I have provided a simple demo, to see the problem just unment at line 15
.
- Please provide an example that exhibits the problem. – geocodezip Commented Sep 28, 2014 at 22:40
- How do I change those to exhibit the issue? – geocodezip Commented Sep 29, 2014 at 3:57
- Here in this fiddle you can see the points are not connected – kiko283 Commented Sep 30, 2014 at 6:55
2 Answers
Reset to default 6Since nobody was able to help me with my problem, I had to solve it myself. I'm answering my own question because this seems to be quite a problem for a lot of people and it's not well enough explained on the web, so this may help developers that have similar problems.
Anyway, let's get to the point. The error was thrown because of Google limitations as OxyDesign suggested, the error was:
google.maps.DirectionsResult.MAX_WAYPOINTS_EXCEEDED
- This is because I sent a request with origin, destination and more than 8 (Google limit) waypoints.
that I easily solved (I just split the array in chunks of 10 points with the last point of one request as the first point of the next), but then I got another error:
google.maps.DirectionsResult.OVER_QUERY_LIMIT
- This is because I tried to send more than 10 (again, Google limit) requests per second.
that took a little more experimenting, searching and testing to solve, but I got it solved.
Now, here is the code that works for me (at least at the time of posting, until Google changes something):
// 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..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..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);
// --------
As you can see, the only real change I made was the showRoute()
function became connectMarkers()
bined with connectMarkersRoute()
and connectMarkersPolyline()
that handle both errors.
Working example can be seen here. It takes a little time to load all route chunks, but at least it works. Hope this helps somebody else too.
Note that there is another Google limit of 2500 Directions
requests per day, so be careful. That being said, this answer works even for a lot larger requests than 200 locations, I have tested with 1250 locations and it worked.
It seems there a limitation for this service Gmaps Waypoints (8 or 23, I tried and it worked until 39, then 40 didn't) and there's no way to do it in other way except with polylines but you don't want it so I think there's no viable solution ...
本文标签: javascriptRequest entity too largegoogle map directions error 413Stack Overflow
版权声明:本文标题:javascript - Request entity too large - google map directions error 413 - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744395294a2604186.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论