127

I have a page, and a Google Maps map is inside a hidden div at first. I then show the div after I click a link, but only the top left of the map shows up.

I tried having this code run after the click:

map0.onResize();

Or:

google.maps.event.trigger(map0, 'resize')

How can I do it?

Here is an image of what I see after showing the div with the hidden map in it:

Alt text

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
leora
  • 188,729
  • 360
  • 878
  • 1,366
  • @Matt Ball - i did get this to work. after i create the google map object i store that in a global variable so i can reference it again later and calling resize now seems to work. I am trying to not have to recreate the map object every time i show it because i allow people to toggle back and forth. – leora Nov 01 '10 at 11:54
  • @ooo that is very simple with the code below. All you need to add is an if condition to check whether the map object has been initialized or not. This was an off-the-cuff code written to address your initial problem which is to load the map correctly. – Philar Nov 01 '10 at 13:35
  • @philar - yup . . thanks here . . thus the upvote :). Either way i need to store the variables at a global level to avoid reinitializing – leora Nov 01 '10 at 14:08
  • In the code below the map object is implicitly a global variable since it has not been declared within the "initialize" function. – Philar Nov 02 '10 at 07:27

23 Answers23

126

I was having the same problem and discovered that when showing the div, calling google.maps.event.trigger(map, 'resize'); appeared to resolve the issue for me.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Eric
  • 1,261
  • 1
  • 8
  • 2
  • 64
    In order to keep the original center of the map right after resizing, consider extending the resize statement this way: var center = map.getCenter(); google.maps.event.trigger(map, 'resize'); map.setCenter(center); – John Doppelmann Feb 22 '13 at 16:13
  • 10
    Not sure why, but I need to wrap the solution inside small setTimeout to get it to work: setTimeout(function() {google.maps.event.trigger(map, 'resize')}, 100); – HoffZ Feb 27 '14 at 13:00
  • @JohnDoppelmann Thanks for the tip! It was not intuitive why it wasn't maintaining center, nor how to force it back. – Noah Duncan May 02 '14 at 23:06
  • Set the map center and zoom level again after triggering the 'resize' event. For more info, see: https://code.google.com/p/gmaps-api-issues/issues/detail?id=1448 – ruhong Apr 05 '15 at 10:10
  • @HoffZ this is probably due to your resizing code firing before the showing effect, the timeout delays it until the show is performed, then the resize can make it's work. You probably can achieve the same effect changing your code order of execution to ensure that when firing the event, div showing is executed before map resizing. – Bardo Sep 16 '15 at 08:31
103

I just tested it myself and here's how I approached it. It is pretty straightforward.

HTML

<div id="map_canvas" style="width:700px; height:500px; margin-left:80px;" ></div>
<button onclick="displayMap()">Show Map</button>

CSS

<style type="text/css">
    #map_canvas {display: none;}
</style>

JavaScript

<script>
    function displayMap()
    {
        document.getElementById( 'map_canvas' ).style.display = "block";
        initialize();
    }

    function initialize()
    {
        // Create the map
        var myOptions = {
            zoom: 14,
            center: new google.maps.LatLng( 0.0, 0.0 ),
            mapTypeId: google.maps.MapTypeId.ROADMAP
        }
        map = new google.maps.Map( document.getElementById( "map_canvas" ), myOptions );
    }
</script>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Philar
  • 3,887
  • 1
  • 24
  • 19
  • So basically you only instantialize the map when the div is shown? Is there any way to do this so that the map object is only instantialized once (on page load)? – lucas Feb 14 '17 at 12:13
  • 1
    I could also suggest a setTimeout delay to call the second function if you are calling a show() to allow for time to resize. – Eric.18 Mar 15 '17 at 17:50
26

Use:

google.maps.event.trigger($("#div_ID")[0], 'resize');

If you don't have a variable map available, it should be the first element (unless you did something stupid) in the div that contains GMAP.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
C S N
  • 391
  • 3
  • 6
  • Are you sure that you can trigger element on a _div_ instead of a _google.map.Map_ object? – Salman A Apr 15 '14 at 12:18
  • @SalmanA - Just checked this & it worked for me (though the Map seems to have a new Center). From previous research I didnt know this was possible either so kudos to CSN – Hal Oct 29 '14 at 02:45
  • 1
    C S N... This works for me, but, it leaves the center position in the wrong spot. My map is initializing like the OP's screen shot, and it's like the center: is centering on the top left corner of my map_canvas. Thoughts on how to get it to draw centered? – Kirk Ross Nov 05 '14 at 23:46
13

I had a Google map inside a Bootstrap tab, which wasn't displaying correctly. This was my fix.

// Previously stored my map object(s) in googleMaps array

$('a[href="#profileTab"]').on('shown', function() {   // When tab is displayed...
    var map = googleMaps[0],
        center = map.getCenter();
    google.maps.event.trigger(map, 'resize');         // fixes map display
    map.setCenter(center);                            // centers map correctly
});
Simon East
  • 55,742
  • 17
  • 139
  • 133
  • 1
    I had to replace 'shown' to 'shown.bs.tab' to get this working for a map that was hidden in an inactive tab. Thanks – Nicola Jan 26 '16 at 11:30
  • I am using SmartWizard 4 and this is the only solution that worked for me and it worked great! I changed `'a[href="#profileTab"]'` to `step-2` which is the name of the DIV containing the map DIV. – GeospatialPython.com Jul 16 '17 at 17:05
7

How to refresh the map when you resize your div

It's not enough just to call google.maps.event.trigger(map, 'resize'); You should reset the center of the map as well.

var map;

var initialize= function (){
    ...
}

var resize = function () {
    if (typeof(map) == "undefined") {) {
        // initialize the map. You only need this if you may not have initialized your map when resize() is called.
        initialize();
    } else {
        // okay, we've got a map and we need to resize it
        var center = map.getCenter();
        google.maps.event.trigger(map, 'resize');
        map.setCenter(center);
    }
}

How to listen for the resize event

Angular (ng-show or ui-bootstrap collapse)

Bind directly to the element's visibility rather than to the value bound to ng-show, because the $watch can fire before the ng-show is updated (so the div will still be invisible).

scope.$watch(function () { return element.is(':visible'); },
    function () {
        resize();
    }
);

jQuery .show()

Use the built in callback

$("#myMapDiv").show(speed, function() { resize(); });

Bootstrap 3 Modal

$('#myModal').on('shown.bs.modal', function() {
    resize();
})
civmeup
  • 71
  • 1
  • 1
  • your bootstrap 3 modal resize method fixed my issue perfectly whereas most of the other suggestions didn't. Thanks! – BrianLegg Dec 10 '16 at 20:21
7

It's also possible to just trigger the native window resize event.

Google Maps will reload itself automatically:

window.dispatchEvent(new Event('resize'));
Philip
  • 23,316
  • 2
  • 31
  • 31
6

If you have a Google Maps map inserted by copy/pasting the iframe code and you don't want to use Google Maps API, this is an easy solution.

Just execute the following JavaScript line when you show the hidden map. It just takes the iframe HTML code and insert it in the same place, so it renders again:

document.getElementById("map-wrapper").innerHTML = document.getElementById("map-wrapper").innerHTML;

jQuery version:

$('#map-wrapper').html( $('#map-wrapper').html() );

The HTML:

<!-- .... -->
<div id="map-wrapper"><iframe src="https://www.google.com/maps/..." /></div>
<!-- .... -->

The following example works for a map initially hidden in a Bootstrap 3 tab:

<script>
$(document).ready( function() {

    /* Detects when the tab is selected */
    $('a[href="#tab-id"]').on('shown.bs.tab', function() {

        /* When the tab is shown the content of the
           wrapper is regenerated and reloaded */

        $('#map-wrapper').html( $('#map-wrapper').html() );

    });
});
</script>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Guscie
  • 2,278
  • 2
  • 26
  • 33
  • 2
    Best solution for anyone who is not loading the Google Map JS but simply using iframe with src url `https://www.google.com/maps/embed/v1/place?..` – gsinha Apr 08 '15 at 03:35
5

I had the same issue, and the google.maps.event.trigger(map, 'resize') wasn't working for me.

I added a timer to update the map after making the div visible...

// Working code

var refreshIntervalId;

function showMap() {
    document.getElementById('divMap').style.display = '';
    refreshIntervalId = setInterval(function () { updateMapTimer() }, 300);
}

function updateMapTimer() {
    clearInterval(refreshIntervalId);
    var map = new google.maps.Map(....
    ....
}

I don't know if it's the more convenient way to do it, but it works!

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Carlos
  • 146
  • 2
  • 6
4

With jQuery you could do something like this. This helped me load a Google Maps map in the Umbraco CMS on a tab that would not be visible from right away.

function waitForVisibleMapElement() {
    setTimeout(function () {
        if ($('#map_canvas').is(":visible")) {
            // Initialize your Google Map here
        } else {
            waitForVisibleMapElement();
        };
    }, 100);
};

waitForVisibleMapElement();
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dennis
  • 66
  • 1
  • 4
  • This is the only solution that worked for me and my problem. I had a google map inside a Materialize.CSS tab that didn't show the map, but showed just a grey background with only the Marker and Google logo in the left corner. I set the tab content div to initialize the map when its visible, and it works perfectly. [Example](http://codepen.io/zzzian/pen/yJzVjy) – Gorgon_Union Jul 09 '16 at 22:56
3

My solution is very simple and efficient:

HTML

<div class="map-wrap">
  <div id="map-canvas"></div>
</div>

CSS

.map-wrap{
  height: 0;
  width: 0;
  overflow: hidden;
}

jQuery

$('.map-wrap').css({ height: 'auto', width: 'auto' }); // For showing your map
$('.map-wrap').css({ height: 0, width: 0 }); // For hiding your map
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
midishero
  • 97
  • 2
  • 4
3

Or if you use gmaps.js, call:

map.refresh();

when your div is shown.

Eric Saboia
  • 1,224
  • 12
  • 14
2

I guess the original question is with a map that is initialized in a hidden div of the page. I solved a similar problem by resizing the map in the hidden div upon document ready, after it is initialized, regardless of its display status.

In my case, I have two maps, one is shown and one is hidden when they are initialized and I don't want to initial a map every time it is shown.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
KYLO
  • 93
  • 11
2

I've found this to work for me:

To hide:

$('.mapWrapper')
.css({
  visibility: 'hidden',
  height: 0
});

To show:

$('.mapWrapper').css({
  visibility: 'visible',
  height: 'auto'
});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Victor S
  • 5,098
  • 5
  • 44
  • 62
2

If used inside Bootstrap v3 tabs, the following should work:

$('a[href="#tab-location"]').on('shown.bs.tab', function(e){
    var center = map.getCenter();
    google.maps.event.trigger(map, 'resize');
    map.setCenter(center);
});

where tab-location is the ID of tab containing map.

Nirmal
  • 9,391
  • 11
  • 57
  • 81
2

Just as John Doppelmann and HoffZ have indicated, put all code together just as follows in your div showing function or onclick event:

setTimeout(function(){
    var center = map.getCenter();
    google.maps.event.trigger(map, 'resize');
    map.setCenter(center);
});

It worked perfectly for me.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

My solution was:

CSS:

.map {
   height: 400px;
   border: #ccc solid 1px;
}

jQuery:

$('.map').width(555); // Width of map canvas
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

I didn't like that the map would load only after the hidden div had become visible. In a carousel, for example, that doesn't really work.

This my solution is to add class to the hidden element to unhide it and hide it with position absolute instead, then render the map, and remove the class after map load.

Tested in Bootstrap Carousel.

HTML

<div class="item loading"><div id="map-canvas"></div></div>

CSS

.loading { display: block; position: absolute; }

JavaScript

$(document).ready(function(){
    // Render map //
    google.maps.event.addListenerOnce(map, 'idle', function(){
        $('.loading').removeClass('loading');
    });
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

Use these lines of code when you want to show a map.

$("#map_view").show("slow"); // Use id of div which you want to show.

var script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&callback=initialize";
document.body.appendChild(script);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ravi Darji
  • 11
  • 5
0
 $("#map_view").show("slow"); // use id of div which you want to show.
     var script = document.createElement("script");
     script.type = "text/javascript";
     script.src = "https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&callback=initialize";
     document.body.appendChild(script);
Ravi Darji
  • 11
  • 5
0

My googleMap div was within a container div with {display:none} until the tab clicked. I had the same problem as the OP. This worked for me:

google.maps.event.addDomListener(window, 'load', setTimeout(initialize, 1));

Stick this code inside and at the end of your code where your container div tab is clicked and reveals your hidden div. The important thing is that your container div has to be visible before initialize can be called.

I tried a number of solutions proposed here and other pages and they didn't work for me.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Leonard
  • 91
  • 2
  • 7
0

Add this code before the div or pass it to a JavaScript file:

<script>
    $(document).on("pageshow", "#div_name", function() {
       initialize();
    });

   function initialize() {
   // Create the map

      var myOptions = {
         zoom: 14,
         center: new google.maps.LatLng(0.0, 0.0),
         mapTypeId: google.maps.MapTypeId.ROADMAP
      }
      map = new google.maps.Map(document.getElementById("div_name"), myOptions);
   }

</script>

This event will be triggered after the div loads so it will refresh the map content without having to press F5.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Balibrera
  • 185
  • 2
  • 7
0

Upon showing the map I am geocoding an address and am then setting the map's center.

The google.maps.event.trigger(map, 'resize'); did not work for me.

I had to use a map.setZoom(14);.

Code is below:

document.getElementById('map').style.display = 'block';
var geocoder = new google.maps.Geocoder();

geocoder.geocode({ 'address': input.value }, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
        map.setCenter(results[0].geometry.location);
        var marker2 = new google.maps.Marker({
            map: map,
            position: results[0].geometry.location
        });
        map.setZoom(14);
        marker2.addListener('dragend', function (event) {
            $('#lat').val(event.latLng.lat());
            $('#lng').val(event.latLng.lng());
        });
    }
});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Andrew
  • 1,126
  • 11
  • 28
-1

function init_map() {
  var myOptions = {
    zoom: 16,
    center: new google.maps.LatLng(0.0, 0.0),
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  map = new google.maps.Map(document.getElementById('gmap_canvas'), myOptions);
  marker = new google.maps.Marker({
    map: map,
    position: new google.maps.LatLng(0.0, 0.0)
  });
  infowindow = new google.maps.InfoWindow({
    content: 'content'
  });
  google.maps.event.addListener(marker, 'click', function() {
    infowindow.open(map, marker);
  });
  infowindow.open(map, marker);
}
google.maps.event.addDomListener(window, 'load', init_map);

jQuery(window).resize(function() {
  init_map();
});
jQuery('.open-map').on('click', function() {
  init_map();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src='https://maps.googleapis.com/maps/api/js?v=3.exp'></script>

<button type="button" class="open-map"></button>
<div style='overflow:hidden;height:250px;width:100%;'>
  <div id='gmap_canvas' style='height:250px;width:100%;'></div>
</div>
Håken Lid
  • 22,318
  • 9
  • 52
  • 67