Is there an event that gets fired when drawing of all features have completed when using the loadGeoJson() method in Google Maps API?
I read that you can listen for "idle" state of the map, but it seems like the map is considered idle when the load is complete, but before features are drawn.
see fiddle below:
https://jsfiddle.net/z3tu0epb/
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: new google.maps.LatLng(40.755690, -73.975938)
});
// Load GeoJSON.
map.data.loadGeoJson(
'https://services5.arcgis.com/GfwWNkhOj9bNBqoJ/arcgis/rest/services/nybb/FeatureServer/0/query?where=1=1&outFields=*&geometryPrecision=8&outSR=4326&f=geojson');
google.maps.event.addListenerOnce(map, 'idle', function() {
alert("map is idle");
});
}
I also know about the addFeature() listener which gets fired when any feature is added to the map, but I need the alert() to run after all the features are added to the map.
Thanks,
I'm afraid there is no feasible way to capture "after drawing all features" event for Data layer. It could be possible if the Data layer had exposed the instance of Drawing manager that is used internally. In this case you could listen to the overlaycomplete event
https://developers.google.com/maps/documentation/javascript/reference#OverlayCompleteEvent
But the Data layer doesn't expose its Drawing manager instance publicly, so you cannot add a listener.
https://developers.google.com/maps/documentation/javascript/reference#Data
The unique thing that you can do is to figure out when all features were loaded (added to collection). In this case you can use a callback function of loadGeoJson(url:string, options?:Data.GeoJsonOptions, callback?:function(Array<Data.Feature>))
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: new google.maps.LatLng(40.755690, -73.975938)
});
// Load GeoJSON.
map.data.loadGeoJson(
'https://services5.arcgis.com/GfwWNkhOj9bNBqoJ/arcgis/rest/services/nybb/FeatureServer/0/query?where=1=1&outFields=*&geometryPrecision=8&outSR=4326&f=geojson',
{},
function(features) {
alert("Loaded " + features.length + " features");
});
google.maps.event.addListenerOnce(map, 'idle', function() {
alert("map is idle");
});
}
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDztlrk_3CnzGHo7CFvLFqE_2bUKEq1JEU&callback=initMap">
</script>
Also, feel free to file a feature request for such event in the Google issue tracker
First time trying to build a map using Google's map API and have hit a roadblock.
I'm trying to make a custom map that has:
Multiple location markers
Custom icons for the markers
A custom url link for each marker so that whenever someone clicks on the marker they go to the url link
The map is for a client that owns a few offices in Soho, London. I've been testing out various code in Google's playground + using w3 schools code tester. I've been finding examples of how to setup the various elements of my map which all work fine when doing it one by one.
However it seems if I wanted to combine all the features of the map that the code needs to be setup differently.
Here's what I have so far:
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>Google Maps Multiple Markers</title>
<script src="http://maps.google.com/maps/api/js?sensor=false"></script>
</head>
<body>
<div id="map" style="width: 100%; height: 300px;"></div>
<script type="text/javascript">
var locations = [
['56-58 Broadwick Street', 51.5053, -0.1481, 5],
['79 Wardour Street', 51.512370, -0.133300, 3],
];
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 14,
center: new google.maps.LatLng(51.5132695,-0.1356768),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var infowindow = new google.maps.InfoWindow();
var marker, i;
var markers = new Array();
for (i = 0; i < locations.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][1], locations[i][2]),
map: map
});
markers.push(marker);
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
infowindow.setContent(locations[i][0]);
infowindow.open(map, marker);
}
})(marker, i));
}
function AutoCenter() {
// Create a new viewpoint bound
var bounds = new google.maps.LatLngBounds();
// Go through each...
$.each(markers, function (index, marker) {
bounds.extend(marker.position);
});
// Fit these bounds to the map
map.fitBounds(bounds);
}
AutoCenter();
</script>
</body>
The idea being that the var locations will be the various office locations that my client own. Each one of these office location markers will link to the relevant office page.
Sorry to have to ask you guys but can anyone lead me in the right direction? I thought I could piece all the code together but it seems like if I want to combine all 3 features the code is setup differently.
Thanks for your time.
For starters, rather than have your JS in the body of your document, move it into the head.
And add an event listener for when the window loads to call an initialize function which creates the map:
google.maps.event.addDomListener(window, 'load', initialize);
And move all the JS that's currently not in any function at all, into that initialize function.
I'm not sure the point of your AutoCenter function. If it's just to make the map expand to fit the bounds of your markers, put this into your initialize function too.
Also this may just be a sample of some data rather than what you're actually doing, but that trailing comma after the last item will cause this array to error in IE:
var locations = [
['56-58 Broadwick Street', 51.5053, -0.1481, 5],
['79 Wardour Street', 51.512370, -0.133300, 3],
];
As part of a much bigger project, we're trying to get a Map on a site using Google's Map API v3. I have followed the simplest steps that Google has laid out, I've tried copying code outright from other working maps. But no matter what I do, all we get is a gray box and no map.
Using Firebug, I can see the information trying to populate the map, but it is simply not displaying. I've tried jquery, jquery libraries specifically made for google maps, nothing is working. I have been up and down the internet and all through google's api help files. Plus, the problem is not local as I've uploaded the file to multiple servers and tested it on multiple browsers and computers. Nothing is working.
At this point it's got to be something stupid that I'm overlooking. Here's my code.
<!DOCTYPE html>
<html>
<head>
<title></title>
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?&sensor=true">
</script>
<script type="text/javascript">
function load()
{
var mapDiv = document.getElementById("map");
var latlng = new google.maps.LatLng(-34.397, 150.644);
var mapOptions =
{
//zoom: 8,
center:latlng,
//backgroundColor: '#ff0000',
mapTypeId: google.maps.MapTypeId.ROADMAP,
imageDefaultUI: true
};
var map = new google.maps.Map(mapDiv, mapOptions);
function createMarker(point, text, title)
{
var marker =
new GMarker(point,{title:title});
return marker;
}
}
</script>
</head>
<body onload="load()">
<div id="map" style="width: 800px; height: 400px;"></div>
</div>
</body>
</html>
This works for me. You simply have to set zoom parameter:
UPDATE (by #user2652379): You need to set BOTH zoom and center options. Just zoom does not work.
<!DOCTYPE html>
<html>
<head>
<title></title>
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>
</script>
<script type="text/javascript">
function load()
{
var mapDiv = document.getElementById("map");
var latlng = new google.maps.LatLng(-34.397, 150.644);
var mapOptions =
{
zoom: 8,
center:latlng,
//backgroundColor: '#ff0000',
mapTypeId: google.maps.MapTypeId.ROADMAP,
//imageDefaultUI: true
};
var map = new google.maps.Map(mapDiv, mapOptions);
// map.addControl(new GSmallMapControl());
// map.addControl(new GMapTypeControl());
// map.addMapType(ROADMAP);
// map.setCenter(
// new GLatLng(37.4419, -122.1419), 13);
}
</script>
</head>
<body onload="load()">
<div id="map" style="width: 800px; height: 400px;"> </div>
</body>
</html>
Another case is when map container is hidden at the moment you initialize the map. E.g. you are doing it inside bootstrap show.bs.modal event, instead of shown.bs.modal
I had the same issue and came across a lot of topics on stackoverflow but none of them had the working solution for me. I eventually found out it was caused to a line of css I had added.
All the elements in the map inherited a
overflow:hidden;
By adding the following line to my CSS it was fixed
#map * {
overflow:visible;
}
I would like to add a quick comment to this since I had the same problem with the zoom parameter set.
I found out that the problem was my theme's css. In my base theme I had the following CSS:
img, embed, object, video {
max-width: 100%;
max-height: 100%;
width: auto;
height: auto;
}
This messed up the rendering of the map and after I removed it, my map renders just fine.
Also beware of having an invalid latitude or longitude value for the map center or your markers. For example, this fiddle shows the Grey Map Of Death because the map center is at latitude 131.044 which is invalid (not from +90:-90).
function initMap() {
var uluru = {lat: 131.044, lng: -25.363};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: uluru
});
var marker = new google.maps.Marker({
position: uluru,
map: map
});
}
In my case, I was working on a map with vue and a modal in the iview library; and during the first render it worked, but any other render displayed the grey screen of death. I fixed the issue by setting a timeout function to display the map after 50 ms to give the modal enough time to render and be visible.
//Time out is crucial for the map to load when opened with vue
setTimeout(() => {
this.showMap(id);
}, 50);
The above example was an earlier fix and a quick hack, i have realized all you need to do is wait for the next tick, on vue you can achieve this by
async mounted(){
await this.$nextTick()
this.showMap(id)
}
or if you are not comfortable with async await you can try the callback option
mounted(){
Vue.nextTick(function () {
this.showMap(id)
})
}
I had the same issue. i was using google maps in Jquery Accordion and when i expand the div the map only consisted a grayed area. I was able to solve this issue by triggering a click event on the specified accordion heading and setting the map container to visible.
Script:
<script type="text/javascript">
var map;
function initMap(lat, lng) {
var myCenter = new google.maps.LatLng(lat, lng);
var mapOptions = {
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: myCenter
};
map = new google.maps.Map(document.getElementById('map'), mapOptions);
}
function ViewMap() {
var latlng = document.getElementById('<%=txt.ClientID%>').value.split(','); // This is where my latlng are placed: 25.12312,55.3212333
$("#showmap").show();
// Sorry for mixing up Jquery and javascript.
initMap(latlng[0], latlng[1]);
}
</script>
ASPX File/Html Markup:
<h3 id="lMap" onclick="ViewMap();"><i class="fa fa-map-o" onclick="ViewMap();"></i>Location Map</h3>
<div style="height:auto" id="showmap">
<div id="map" style="width: 850px; height: 550px; overflow: visible"></div>
</div>
I realise this is an old thread, but this may help someone in the future.
Struggled with this for hours, but after discovering that the Google Map is rendered with a grey box overlay if the map is rendered while not being visible, I used a bit of jQuery to make my application only instantiate and render the map if the map is visible, like such:
if ($("#myHomeMapHolder").is(":visible")) {
if (homemap == null) {
homemap = new google.maps.Map(document.getElementById("myHomeMapHolder"), myOptions);
google.maps.event.addListener(homemap, 'click', function (event) {
placeHomeMarker(event.latLng);
});
} else {
homemap.setCenter(myLatlng);
}
if (homemarker == null) {
homemarker = new google.maps.Marker({
position: myLatlng,
map: homemap,
title: "Home"
});
} else {
homemarker.setPosition(myLatlng);
}
}
And voila, my map is only rendered if the map holder is visible, so it never renders with a grey box.
For anyone wondering, myHomeMapHolder is a div which the map sits inside.
In my case, someone had dropped this little prize in some responsive.css file:
img {
max-width: 100% !important;
}
Removed that and all is fine now.
I had this issue with a site I'm working on too. We're doing some things to all <img> tags for responsiveness. This fix is working for us for the map:
img {max-width: initial !important;}
For those who might be stuck regardless of the nice solutions provided here, try setting the height and width of your container directly in the html markup instead of a stylesheet ie.
<div id="map-container" style="width: 100%; height: 300px;"></div>
happy mapping!
This may not be the case for everyone, but maybe it can help someone.
I was creating markers in my map from data attributes placed on the map element like this: data-1-lat="2" data-1-lon="3" data-text="foo". I was putting them in an array based on the order they were placed in the data attributes.
The problem is that IE and Edge (for some mad reason) invert the order of the data attributes in the HTML tag, therefore I wasn't able to correctly extract them from the data attributes.
None of the existing answers helped me because my problem was that Apollo was adding extra properties ("__typename" fields) to my MapOptions object.
In other words, the JSON looked like this:
mapOptions {"__typename":"MapOptions","center":{"__typename":"GeoCoordinates","lat":33.953056,"lng":-83.9925},"zoom":10}
Once I realized that those extra properties were problematic, this is how I solved it (using TypeScript):
function getCleanedMapOptions(mapOptionsGql: google.maps.MapOptions): google.maps.MapOptions {
const mapOptions = { ...mapOptionsGql };
const lat: number = mapOptions.center.lat as number;
const lng: number = mapOptions.center.lng as number;
const mapOptionsCleaned = {
center: new google.maps.LatLng({ lat, lng }),
zoom: mapOptions.zoom,
};
return mapOptionsCleaned;
}
export function createMap(mapOptions: google.maps.MapOptions): google.maps.Map {
const mapOptionsCleaned = getCleanedMapOptions(mapOptions);
const map = new google.maps.Map(document.getElementById('map') as HTMLElement, mapOptionsCleaned);
return map;
}
In my case (version is 3.30 when submitting this), it was because the div id MUST be "map"
<div id="map"></div>
...
document.getElementById("map")
I want auto complete results only from Mexico, for this I am trying the code below and adding bounds to ensure put Mexico in a rectangle, however I still get resutlts from outside of the country.
How Can I fix this ?
Here is the html and the same code is below:
<!DOCTYPE html>
<html>
<head>
<title>Google Maps JavaScript API v3 Test: Places Autocomplete</title>
<script src="http://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"
type="text/javascript"></script>
<style type="text/css">
body {
font-family: sans-serif;
font-size: 14px;
}
#map_canvas {
height: 1px;
width: 1px;
display:hidden;
}
#searchTextField{
width:500px;
}
</style>
<script type="text/javascript">
function initialize() {
var options = {
bounds: google.maps.LatLngBounds( google.maps.LatLng(33.1613, -118.4766), google.maps.LatLng(14.3770, -84.8145) )
};
var input = document.getElementById('searchTextField');
var autocomplete = new google.maps.places.Autocomplete(input, options);
var infowindow = new google.maps.InfoWindow();
google.maps.event.addListener(autocomplete, 'place_changed', function() {
infowindow.close();
var place = autocomplete.getPlace();
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<input id="searchTextField" type="text" size="50"> <div id="map_canvas"></div>
</body>
</html>
Now you can accomplish what you want with:
componentRestrictions: {country: 'mx'}
in your options argument to build the Autocomplete object.
This is a hard restriction, unlike bounds. It's only for countries, but that's what you want anyway.
var options = {
types: ['geocode'],
componentRestrictions: {country: "mx"}
};
Setting the bounds is not how you do location biasing. See "Location Biasing" in this documentation:
http://code.google.com/apis/maps/documentation/places/autocomplete.html#location_biasing
You may bias results to a specified circle by passing a location and a
radius parameter. Doing so instructs the Place service to prefer
showing results within that circle; results outside of the defined
area may still be displayed.
Also, take a look at this sample here:
http://gmaps-samples-v3.googlecode.com/svn/trunk/places/places-search.html
I should also, note, I don't think it's possible to just specify "Mexico only". You can do searches within a radius, but you can't specify just a country.
As the previous answer suggested and as it says in the API, you can only bias towards a set of results. I would suggest making a smaller bounds based on somewhere in the middle of Mexico or even Mexico City to make the bias stronger.
I'm new to google maps and want to use google map javascript API to display houses as markers. I want a person to be able to click on the map to place a marker, which can be clicked again to be removed or dragged to another location on the map. Then, I want the script to get the cordinates(lat and long) so that I can ad it to a database table. Any idea how I should do this? I'm using PHP in codeIgniter.
A good place to start would be to check out the reference manual: http://code.google.com/apis/maps/documentation/javascript/reference.html
If you look at map there you can see that it has an event called "click". What you do is after your map has been initialized you make an eventlistener, that listens to the click event. When that occurs you then place a marker on that location, and add an eventlistener on that marker for the click event if you want to remove it, or make it draggable if you want to drag it.
Remember to store your markers in an array if you ever want to use the information they are holding again.
I hope this helped.
I am late to the party. Please find below code snipet.
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<script>
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 8
});
var marker;
map.addListener('click', function(e) {
if(marker){
var latlng = new google.maps.LatLng(e.latLng.lat(), e.latLng.lng());
marker.setPosition(latlng);
}else{
marker = new google.maps.Marker({
position: {lat : e.latLng.lat(), lng : e.latLng.lng()},
map: map
})
}
alert("lat : "+e.latLng.lat()+ "; lng : "+e.latLng.lng())
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDNPpCPQOwkMotaDj0IgHQ7HDAE8cz6-4U&callback=initMap"
async defer></script>