Cómo lidiar con el mapa de Google dentro de un div oculto (Imagen actualizada)


127

Tengo una página y un mapa de Google está dentro de un div oculto al principio. Luego muestro el div después de hacer clic en un enlace, pero solo aparece la parte superior izquierda del mapa.

Traté de ejecutar este código después del clic:

    map0.onResize();

o:

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

algunas ideas. Aquí hay una imagen de lo que veo después de mostrar el div con el mapa oculto.texto alternativo


Ya hay una serie de preguntas sobre SO sobre esto, incluida la visualización del mapa de Google desde un área oculta
Matt Ball el

@Matt Ball: como lo actualicé, intenté agregar el evento de cambio de tamaño allí pero todavía no funcionaba
leora

@Matt Ball: conseguí que esto funcione. después de crear el objeto de Google Map, lo almaceno en una variable global para poder consultarlo más tarde y llamar a redimensionar ahora parece funcionar. Estoy tratando de no tener que recrear el objeto del mapa cada vez que lo muestro porque permito que las personas cambien de un lado a otro.
Leora

@ooo eso es muy simple con el siguiente código. Todo lo que necesita agregar es una condición if para verificar si el objeto del mapa se ha inicializado o no. Este fue un código improvisado escrito para abordar su problema inicial que consiste en cargar el mapa correctamente.
Philar 01 de

@philar - sí. . gracias aqui . así el voto a favor :). De cualquier manera necesito para almacenar las variables a nivel mundial para evitar la reinicialización
Leora

Respuestas:


103

Solo lo probé yo mismo y así es como lo enfoqué. Bastante sencillo, avíseme si necesita alguna aclaración

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>

Entonces, ¿básicamente solo instancializas el mapa cuando se muestra el div? ¿Hay alguna forma de hacer esto para que el objeto del mapa solo se instancelice una vez (en la carga de la página)?
lucas

1
También podría sugerir un retraso de setTimeout para llamar a la segunda función si está llamando a un show () para permitir que el tiempo cambie de tamaño.
Eric.18

126

Estaba teniendo el mismo problema y descubrí que cuando mostraba el div, llamaba google.maps.event.trigger(map, 'resize'); y parece resolver el problema por mí.


64
Para mantener el centro original del mapa justo después de cambiar el tamaño, considere extender la declaración de cambio de tamaño de esta manera: var center = map.getCenter (); google.maps.event.trigger (mapa, 'cambiar tamaño'); map.setCenter (centro);
John Doppelmann

10
No estoy seguro de por qué, pero necesito envolver la solución dentro de setTimeout pequeño para que funcione: setTimeout (function () {google.maps.event.trigger (map, 'resize')}, 100);
HoffZ

@JohnDoppelmann Gracias por el consejo! No era intuitivo por qué no mantenía el centro, ni cómo forzarlo a retroceder.
Noah Duncan

Establezca el centro del mapa y el nivel de zoom nuevamente después de activar el evento 'cambiar tamaño'. Para obtener más información, consulte: code.google.com/p/gmaps-api-issues/issues/detail?id=1448
ruhong

@HoffZ esto probablemente se deba a que su código de cambio de tamaño se activa antes del efecto de visualización, el tiempo de espera lo retrasa hasta que se realiza el espectáculo, luego el cambio de tamaño puede hacer que funcione. Probablemente pueda lograr el mismo efecto cambiando el orden de ejecución de su código para asegurarse de que al disparar el evento, se muestre div antes del cambio de tamaño del mapa.
Bardo

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

Si no tiene un mapa variable disponible, debería ser el primer elemento (a menos que haya hecho algo estúpido) en el divque contiene GMAP.


¿Estás seguro de que puedes activar un elemento en un div en lugar de un objeto google.map.Map ?
Salman A

@SalmanA: acabo de comprobar esto y funcionó para mí (aunque el Mapa parece tener un nuevo Centro). De investigaciones anteriores no sabía que esto era posible, así que felicitaciones a CSN
Hal

CS N ... Esto funciona para mí, pero deja la posición central en el lugar equivocado. Mi mapa se está inicializando como la captura de pantalla del OP, y es como el centro: está centrado en la esquina superior izquierda de mis map_canvas. ¿Pensamientos sobre cómo hacer que se dibuje centrado?
Kirk Ross el

13

Tenía un mapa de Google dentro de una pestaña Bootstrap, que no se mostraba correctamente. Esta fue mi solución.

// 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
});

1
Tuve que reemplazar 'shown' por 'shown.bs.tab' para que esto funcione para un mapa que estaba oculto en una pestaña inactiva. Gracias
Nicola

Estoy usando SmartWizard 4 y esta es la única solución que funcionó para mí y funcionó muy bien. Cambié 'a[href="#profileTab"]'a step-2cuál es el nombre del DIV que contiene el mapa DIV.
GeospatialPython.com

7

Cómo actualizar el mapa cuando cambias el tamaño de tu div

No basta con llamar. google.maps.event.trigger(map, 'resize');También debe restablecer el centro del mapa.

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);
    }
}

Cómo escuchar el evento de cambio de tamaño

Angular (colapso ng-show o ui-bootstrap)

Vincula directamente a la visibilidad del elemento en lugar de al valor vinculado a ng-show, porque $ watch puede dispararse antes de que se actualice ng-show (por lo que el div seguirá siendo invisible).

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

jQuery .show ()

Use la devolución de llamada incorporada

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

Bootstrap 3 Modal

$('#myModal').on('shown.bs.modal', function() {
    resize();
})

su método de redimensionamiento modal bootstrap 3 solucionó mi problema perfectamente, mientras que la mayoría de las otras sugerencias no lo hicieron. ¡Gracias!
BrianLegg

6

Si tiene un Google Map insertado copiando / pegando el código del iframe y no desea utilizar la API de Google Maps , esta es una solución fácil. Simplemente ejecute la siguiente línea de JavaScript cuando muestre el mapa oculto. Simplemente toma el código HTML del iframe y lo inserta en el mismo lugar, por lo que se vuelve a mostrar:

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

Versión de jQuery:

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

El HTML:

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

El siguiente ejemplo funciona para un mapa inicialmente oculto en una pestaña Bootstrap 3:

<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>

2
La mejor solución para cualquier persona que no esté cargando el Google Map JS sino simplemente usando iframe con src urlhttps://www.google.com/maps/embed/v1/place?..
gsinha

6

También es posible activar el evento de cambio de tamaño de la ventana nativa.

Google Maps se recargará automáticamente:

window.dispatchEvent(new Event('resize'));

5

Tuve el mismo problema, el google.maps.event.trigger(map, 'resize') no funcionaba para mí.

Lo que hice fue poner un temporizador para actualizar el mapa después de poner visible el div...

//CODE WORKING

var refreshIntervalId;

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

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

No sé si es la forma más conveniente de hacerlo, ¡pero funciona!


use setTimeout para esperar una vez.
Joe Austin

4

Con jQuery podrías hacer algo como esto. Esto me ayudó a cargar un mapa de Google en Umbraco CMS en una pestaña que no sería visible de inmediato.

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

waitForVisibleMapElement();

Esta es la única solución que funcionó para mí y mi problema. Tenía un mapa de Google dentro de una pestaña Materialise.CSS que no mostraba el mapa, pero mostraba solo un fondo gris con solo el Marcador y el logotipo de Google en la esquina izquierda. Configuré el contenido de la pestaña div para inicializar el mapa cuando es visible, y funciona perfectamente. Ejemplo
Gorgon_Union el

3

Mi solución es muy simple y eficiente:

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


2

Supongo que la pregunta original es con un mapa que se inicializa en un div oculto de la página. Resolví un problema similar cambiando el tamaño del mapa en el div oculto cuando el documento está listo, después de que se inicializa, independientemente de su estado de visualización. En mi caso, tengo 2 mapas, uno se muestra y otro está oculto cuando se inicializan y no quiero iniciar un mapa cada vez que se muestra. Es una publicación antigua, pero espero que ayude a cualquiera que esté buscando.


2

He encontrado que esto funciona para mí:

esconder:

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

mostrar:

    $('.mapWrapper').css({
      visibility: 'visible',
      height: 'auto'
    });

2

Si se usa dentro de las pestañas Bootstrap v3, lo siguiente debería funcionar:

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

donde tab-locationestá la ID de la pestaña que contiene el mapa.


2

Tal como lo han indicado John Doppelmann y HoffZ, junte todo el código de la siguiente manera en su función de visualización div o evento onclick:

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

Funcionó perfectamente para mí


0

Mi solución fue:

CSS:

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

jQuery:

$('.map').width(555); // width of map canvas

0

No me gustó que el mapa se cargara solo después de que el div oculto se hiciera visible. En un carrusel, por ejemplo, eso realmente no funciona.

Esta es mi solución: agregar clase al elemento oculto para mostrarlo y ocultarlo con la posición absoluta, luego renderizar el mapa y eliminar la clase después de la carga del mapa.

Probado en Bootstrap Carrousel.

HTML

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

CSS

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

JS

$(document).ready(function(){
    // render map //
    google.maps.event.addListenerOnce(map, 'idle', function(){
        $('.loading').removeClass('loading');
    });
}

0

use esta línea de códigos cuando quiera mostrar el mapa.

               $("#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);

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);

0

Primer comentario. Mi googleMap div estaba dentro de un contenedor div con {display: none} hasta que se hizo clic en la pestaña. Tenía el mismo problema que OP. Esto funcionó para mí:

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

Pegue este código dentro y al final de su código donde se hace clic en la pestaña div del contenedor y revela su div oculto. Lo importante es que su contenedor div debe ser visible antes de que se pueda llamar a initialize.

Probé una serie de soluciones propuestas aquí y otras páginas y no funcionaron para mí. Hazme saber si esto funciona para ti. Gracias.


0

Agregue este código antes del div o páselo a un archivo js:

<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>

Este evento se activará después de que se cargue el div, por lo que actualizará el contenido del mapa sin tener que presionar F5


0

Al mostrar el mapa, estoy geocodificando una dirección y luego configurando el centro de mapas. losgoogle.maps.event.trigger(map, 'resize'); no funcionó para mí.

Tuve que usar un map.setZoom(14);

Código a continuación:

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());
                });

            }
        });

-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>

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.