12π
This response came from the Server (google). So youβre not allowed to request such long URLs.
See the google api doc for more infos:
Static Map URLs are restricted to 2048 characters in size. In practice, you will probably not have need for URLs longer than this, unless you produce complicated maps with a high number of markers and paths.
20π
The way i see it is either you reduce precision of your markers in order to gain space in the URL.
(i.e. markers=13.72326,-86.13705β->markers=13.73,-86.14) resulting in placing the markers in a gridβ¦
Or you go with a non static api
- [Django]-Add a custom button to a Django application's admin page
- [Django]-How to format time in django-rest-framework's serializer?
- [Django]-How to get an ImageField URL within a template?
6π
Officially you can use 8192 characters
This depends on browser and server, but as a thumb rule 8192 characters should be OK.
Server
Google Maps Static server https://maps.googleapis.com/maps/api/staticmap at 30 July 2019.
Google Static Maps Docs claims that:
Maps Static API URLs are restricted to 8192 characters in size. In practice, you will probably not have need for URLs longer than this, unless you produce complicated maps with a high number of markers and paths. Note, however, that certain characters may be URL-encoded by browsers and/or services before sending them off to the API, resulting in increased character usage.
But in practice, Iβm getting errors (413 Payload Too Large) after 15k~ characters mark (30 July 2019):
βββββββββββ¦ββββββββββββββββββ¦βββββββββββββββββββ
β Browser β Browser Version β Valid URL Length β
β ββββββββββ¬ββββββββββββββββββ¬βββββββββββββββββββ£
β Chrome β 75 β 15489 β
β Firefox β 68 β 15761 β
β Safari β 12.1 β 15690 β
βββββββββββ©ββββββββββββββββββ©βββββββββββββββββββ
This is based on data got by using fetch()
in browser console. Iβd assume that Google Static Maps server accepts requests (whole request, not just path) no larger than 16k in size.
Solutions
Reduce Precision
Our company policy is that coordinate data below 6 decimal places (111.32 mm) is useless (considering our market share uses phones and commercial GPS devices).
const decimalPlaces = 6 // decimal places count
const decimalPowered = 10 ** decimalPlaces // 1_000_000
const trim = number => Math.round(number * decimalPowered) / decimalPowered // function that trims number
const coordinates = [
[51.838245, -111.834991],
[51.8331, -111.835],
[51.831007022306, -111.8232751234],
[51.838244686875, -111.82327418214]
]
const trimmedCoordinates = coordinates.map(coordinate => coordinate.map(trim))
console.log(trimmedCoordinates)
Encode coordinates
If you have access to encoder you can replace path with an encoded path (use String
manipulation instead of URLSearchParams
, because searchParams
automatically uses encodeURI, which would break your encoded path):
const coordinates = [
[51.838245, -111.834991],
[51.8331, -111.835],
[51.831007022306, -111.8232751234],
[51.838244686875, -111.82327418214]
].map(([lng, lat]) => ({ lng, lat }))
// path should be MVCArray<LatLng>|Array<LatLng>, if you have Polygon or Polyline, getPath() method should be fine
const path = coordinates.map(coordinate => new google.maps.LatLng(coordinate))
const encoded = google.maps.geometry.encoding.encodePath(
path
);
return (
url.href +
`&path=fillcolor:${color}|color:${color}|enc:${encoded}`
);
https://developers.google.com/maps/documentation/maps-static/dev-guide
https://developers.google.com/maps/documentation/utilities/polylinealgorithm
https://developers.google.com/maps/documentation/javascript/geometry#Encoding
Handle Errors
- Use placeholder image
- Check if
href.length > 8192
before request - Trim coordinates
- Encode path
- Check if
!res.ok && res.status === 413
and display error for user which claims that map is too detailed - Use fallback image
- [Django]-How do I match the question mark character in a Django URL?
- [Django]-Adding css class to field on validation error in django
- [Django]-How to force application version on AWS Elastic Beanstalk
5π
- [Django]-Suddenly when running tests I get "TypeError: 'NoneType' object is not iterable
- [Django]-Missing Table When Running Django Unittest with Sqlite3
- [Django]-Get the list of checkbox post in django views
4π
You can encode your Polylines and make them shorter .
Here is the example which can help you how to short your Polylines
I am using the php library to short the length
here is the link of library https://github.com/danmandle/encoded-polyline-stitcher
if you use this library
(51.838245,-111.834991|51.833179,-111.83503|51.831007022306,-111.8232751234|51.838244686875,-111.82327418214) = (atk{HtwqiTt^FpLmhAgl@)
Here important point is if you use short url you have to use βenc:β keyword
(fillcolor:0xAA000033|color:0xFFFFFF00|51.838245,-111.834991|51.833179,-111.83503|51.831007022306,-111.8232751234|51.838244686875,-111.82327418214) = (fillcolor:0xAA000033|color:0xFFFFFF00|enc:atk{HtwqiTt^FpLmhAgl@)
The Library is available for other languages as well if you are not using php .
I hope that it helps others
- [Django]-Django admin file upload with current model id
- [Django]-Github issues api 401, why? (django)
- [Django]-Django dynamic forms β on-the-fly field population?
3π
Google recently extended the URL limit to 8192, but if you need more than that, you still need to simplify your map or resort to other tricks.
- [Django]-How can I chain Django's "in" and "iexact" queryset field lookups?
- [Django]-Django Rest Framework model serializer with out unique together validation
- [Django]-Missing Table When Running Django Unittest with Sqlite3
2π
URLs over 2000-ish characters arenβt valid. Is your querystring longer than that?
Also see this post
- [Django]-Django composite unique on multiple model fields
- [Django]-Create custom buttons in admin change_form in Django
- [Django]-Github issues api 401, why? (django)
1π
You might also use marker clustering on a static map:
http://www.appelsiini.net/projects/php_google_maps/cluster.html
http://www.appelsiini.net/2008/11/introduction-to-marker-clustering-with-google-maps
- [Django]-Django 1.8 KeyError: 'manager' on relationship
- [Django]-How can I chain Django's "in" and "iexact" queryset field lookups?
- [Django]-Django + Ajax
1π
Very old thread but I had to cobble together something to tackle this very problem in a hurry. Sharing here in case anyone else had the same problem.
It takes an array of markers in the form:
$points =
[0] => Array
(
[lat] => 52.1916312
[lng] => -1.7083109
)
[1] => Array
(
[lat] => 50.2681918
[lng] => 2.5616710
)
...
...
...
[500] => Array
(
[lat] => 49.1821968
[lng] => 2.1671056
)
Max url length is 2048 chars so it first reduces accuracy of the lat lng to
$marker_accuracy (4) then starts removing markers from the middle.
Removing markers from the middle could be improved a lot as it does
it one at a time
$map_url = make_static_map($points);
function make_static_map($points,$reduce_len=false,$reduce_count=false){
$grp_points = array();
$grps = array();
$url = array();
$max_len = 0;
$width = 640; //max 640 :(
$height = 640; //max 640 :(
$marker_accuracy = 4; //Lat lng to 4 decimal places minimum, 3 would be less accurate
$url[] = 'http://maps.googleapis.com/maps/api/staticmap?';
$url[] = '&size='.$width.'x'.$height.'&scale=2';
$url[] = '&markers=';
if($reduce_count){ //Last resort to shortening this
array_splice($points, ceil(count($points)/2), 1);
}
foreach($points as $i => $point){
if($reduce_len){
$point['lat'] = number_format($point['lat'], $reduce_len, '.', '');
$points[$i]['lat'] = $point['lat'];
$point['lng'] = number_format($point['lng'], $reduce_len, '.', '');
$points[$i]['lng'] = $point['lng'];
}else{
$t_len = max(strlen($point['lat']),strlen($point['lng']));
if($t_len>$max_len){
$max_len = $t_len;
}
}
$grps[] = array($point['lat'],$point['lng']);
}
$grps = remove_duplicate_points($grps);
foreach($grps as $grp){
$grp_points[] = implode(',',$grp);
}
$url[] = implode('|',$grp_points);
$url[] = '&sensor=false';
$url = implode('',$url);
if(strlen($url) > 2048){
// Bugger, too long for google
if($max_len>$marker_accuracy){
// Reduce the length of lat lng decimal places
return(make_static_map($points,$max_len-1,false));
}else{
// Reduce the number of lat lng markers (from center)
return(make_static_map($points,false,true));
}
}else{
return($url);
}
}
function remove_duplicate_points($points){
$points = array_map('serialize', $points);
$points = array_unique($points);
return(array_map('unserialize', $points));
}
- [Django]-How to format time in django-rest-framework's serializer?
- [Django]-How can I access environment variables directly in a Django template?
- [Django]-"<Message: title>" needs to have a value for field "id" before this many-to-many relationship can be used.
1π
Use osm-static-maps, itβs a clone of google static maps but you can send any amount of data to it. https://github.com/jperelli/osm-static-maps
Disclaimer: Iβm the author.
- [Django]-Django switching, for a block of code, switch the language so translations are done in one language
- [Django]-Custom django admin templates not working
- [Django]-Disable session creation in Django