jak radzić sobie z mapą Google wewnątrz ukrytego div (zaktualizowane zdjęcie)

127

Mam stronę, a mapa Google jest początkowo wewnątrz ukrytego elementu div. Następnie pokazuję element DIV po kliknięciu łącza, ale pojawia się tylko lewy górny róg mapy.

próbowałem uruchomić ten kod po kliknięciu:

    map0.onResize();

lub:

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

jakieś pomysły. tutaj jest obraz tego, co widzę po pokazaniu div z ukrytą mapą.tekst alternatywny

leora
źródło
Jest już wiele pytań na ten temat, w tym wyświetlanie mapy Google z ukrytego obszaru
Matt Ball
@Matt Ball - zgodnie z aktualizacją próbowałem dodać tam wydarzenie zmiany rozmiaru, ale nadal nie działa
leora
@Matt Ball - udało mi się to. po utworzeniu obiektu mapy google przechowuję go w zmiennej globalnej, aby móc później odwołać się do niego, a wywołanie zmiany rozmiaru wydaje się teraz działać. Staram się nie odtwarzać obiektu mapy za każdym razem, gdy go pokazuję, ponieważ pozwalam ludziom przełączać się tam iz powrotem.
leora
@ooo to jest bardzo proste dzięki poniższemu kodowi. Wszystko, co musisz dodać, to warunek if, aby sprawdzić, czy obiekt mapy został zainicjowany, czy nie. To był spontaniczny kod napisany w celu rozwiązania początkowego problemu, jakim jest prawidłowe ładowanie mapy.
Philar
@philar - tak. . dzięki tutaj. . stąd głosy za :). Tak czy inaczej, muszę przechowywać zmienne na poziomie globalnym, aby uniknąć ponownej inicjalizacji
leora

Odpowiedzi:

103

Właśnie przetestowałem to sam i oto jak do tego podszedłem. Całkiem proste, daj mi znać, jeśli potrzebujesz wyjaśnień

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>
Philar
źródło
Więc w zasadzie instancjonowanie mapy następuje tylko wtedy, gdy wyświetlany jest element div? Czy istnieje sposób, aby to zrobić, aby obiekt mapy był tworzony tylko raz (podczas ładowania strony)?
lucas
1
Mógłbym również zasugerować opóźnienie setTimeout do wywołania drugiej funkcji, jeśli wywołujesz funkcję show (), aby dać czas na zmianę rozmiaru.
Eric
126

Miałem ten sam problem i odkryłem, że po wyświetleniu elementu div, zadzwoń google.maps.event.trigger(map, 'resize');i wygląda na to, że rozwiązuje problem.

Eric
źródło
64
Aby zachować oryginalny środek mapy zaraz po zmianie rozmiaru, rozważ rozszerzenie instrukcji resize w ten sposób: var center = map.getCenter (); google.maps.event.trigger (mapa, 'zmień rozmiar'); map.setCenter (w środku);
John Doppelmann
10
Nie wiem dlaczego, ale muszę zawrzeć rozwiązanie w małym setTimeout, aby działało: setTimeout (function () {google.maps.event.trigger (map, 'resize')}, 100);
HoffZ
@JohnDoppelmann Dzięki za cynk! Nie było intuicyjne, dlaczego nie utrzymywał środka ani jak go zmusić.
Noah Duncan
Po wywołaniu zdarzenia zmiany rozmiaru ponownie ustaw środek mapy i poziom powiększenia. Aby uzyskać więcej informacji, zobacz: code.google.com/p/gmaps-api-issues/issues/detail?id=1448
ruhong.
@HoffZ jest to prawdopodobnie spowodowane uruchomieniem kodu zmiany rozmiaru przed efektem wyświetlania, limit czasu opóźnia go do momentu wykonania pokazu, a następnie zmiana rozmiaru może sprawić, że to zadziała. Prawdopodobnie możesz osiągnąć ten sam efekt zmieniając kolejność wykonywania kodu, aby zapewnić, że podczas uruchamiania zdarzenia, wyświetlanie div jest wykonywane przed zmianą rozmiaru mapy.
Bardo
26
google.maps.event.trigger($("#div_ID")[0], 'resize');

Jeśli nie masz dostępnej mapy zmiennych, powinien to być pierwszy element (chyba że zrobiłeś coś głupiego) w tym, divktóry zawiera GMAP.

CSN
źródło
Czy na pewno możesz wyzwolić element w elemencie div zamiast w obiekcie google.map.Map ?
Salman A
@SalmanA - Właśnie to sprawdziłem i zadziałało dla mnie (chociaż mapa wydaje się mieć nowe centrum). Z poprzednich badań nie wiedziałem, że jest to możliwe, więc chwała CSN
Hal
CS N ... To działa dla mnie, ale pozostawia środkową pozycję w złym miejscu. Moja mapa inicjuje się jak zrzut ekranu OP i jest jak środek: jest wyśrodkowany w lewym górnym rogu mojego map_canvas. Zastanawiasz się, jak sprawić, by rysowanie było wyśrodkowane?
Kirk Ross,
13

Miałem mapę Google na karcie Bootstrap, która nie wyświetlała się poprawnie. To była moja poprawka.

// 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
źródło
1
Musiałem zamienić `` shown '' na `` shown.bs.tab '', aby to działało dla mapy, która była ukryta w nieaktywnej karcie. Dzięki
Nicola
Używam SmartWizard 4 i jest to jedyne rozwiązanie, które zadziałało i zadziałało świetnie! Zmieniłem 'a[href="#profileTab"]'na step-2która jest nazwa DIV zawierającej mapę DIV.
GeospatialPython.com,
7

Jak odświeżyć mapę podczas zmiany rozmiaru div

Nie wystarczy tylko zadzwonić. google.maps.event.trigger(map, 'resize');Powinieneś także zresetować środek mapy.

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

Jak nasłuchiwać zdarzenia zmiany rozmiaru

Angular (zwijanie ng-show lub ui-bootstrap)

Powiąż bezpośrednio z widocznością elementu, a nie z wartością przypisaną do ng-show, ponieważ $ watch może uruchomić się przed zaktualizowaniem ng-show (więc element div będzie nadal niewidoczny).

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

jQuery .show ()

Użyj wbudowanego wywołania zwrotnego

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

Bootstrap 3 Modal

$('#myModal').on('shown.bs.modal', function() {
    resize();
})
civmeup
źródło
Twoja metoda zmiany rozmiaru modalnego bootstrap 3 doskonale rozwiązała mój problem, podczas gdy większość innych sugestii nie. Dzięki!
BrianLegg,
6

Jeśli masz mapę Google wstawioną przez skopiowanie / wklejenie kodu iframe i nie chcesz korzystać z interfejsu API Map Google , jest to łatwe rozwiązanie. Po prostu wykonaj poniższą linię javascript, gdy pokażesz ukrytą mapę. Po prostu pobiera kod HTML iframe i wstawia go w tym samym miejscu, więc renderuje się ponownie:

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

Wersja jQuery:

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

HTML:

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

Poniższy przykład działa dla mapy początkowo ukrytej na karcie 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>
Gustavo
źródło
2
Najlepsze rozwiązanie dla każdego, kto nie ładuje Google Map JS, ale po prostu używa iframe z url srchttps://www.google.com/maps/embed/v1/place?..
gsinha
6

Możliwe jest również wyzwolenie natywnego zdarzenia zmiany rozmiaru okna.

Mapy Google załadują się ponownie automatycznie:

window.dispatchEvent(new Event('resize'));
Philip
źródło
5

Miałem ten sam problem, google.maps.event.trigger(map, 'resize')to nie działało dla mnie.

To, co zrobiłem, to ustawić timer, aby zaktualizować mapę po umieszczeniu widocznego 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(....
    ....
}

Nie wiem, czy to wygodniejszy sposób, ale działa!

Carlos
źródło
użyj setTimeout, aby poczekać raz.
Joe Austin
4

Z jQuery można zrobić coś takiego. Pomogło mi to załadować mapę Google w Umbraco CMS na karcie, która nie byłaby widoczna od razu.

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

waitForVisibleMapElement();
Dennis
źródło
To jedyne rozwiązanie, które zadziałało dla mnie i mojego problemu. Miałem mapę Google w zakładce Materialize.CSS, która nie pokazywała mapy, ale pokazywała tylko szare tło z tylko logo Marker i Google w lewym rogu. Ustawiłem element div zawartości karty tak, aby inicjował mapę, gdy jest widoczna, i działa idealnie. Przykład
Gorgon_Union
3

Moje rozwiązanie jest bardzo proste i wydajne:

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
midishero
źródło
3

Jeśli używasz gmaps.js , zadzwoń:

map.refresh();

kiedy wyświetlany jest Twój element DIV.

Eric Saboia
źródło
2

Wydaje mi się, że pierwotne pytanie dotyczy mapy zainicjowanej w ukrytym elemencie div na stronie. Rozwiązałem podobny problem, zmieniając rozmiar mapy w ukrytym div, gdy dokument jest gotowy, po jego zainicjowaniu, niezależnie od statusu wyświetlania. W moim przypadku mam 2 mapy, jedna jest wyświetlana, a druga jest ukryta, gdy są inicjalizowane, i nie chcę inicjować mapy za każdym razem, gdy jest wyświetlana. To stary post, ale mam nadzieję, że pomoże każdemu, kto szuka.

KYLO
źródło
2

Odkryłem, że to działa dla mnie:

ukryć:

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

pokazywać:

    $('.mapWrapper').css({
      visibility: 'visible',
      height: 'auto'
    });
Victor S.
źródło
2

W przypadku użycia w zakładkach Bootstrap v3, poniższe powinny działać:

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

gdzie tab-locationto identyfikator zakładki zawierającej mapę.

Nirmal
źródło
2

Tak jak wskazali John Doppelmann i HoffZ, umieść cały kod razem w następujący sposób w funkcji wyświetlania div lub zdarzeniu onclick:

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

U mnie zadziałało idealnie

Victor Tarango
źródło
0

Moje rozwiązanie brzmiało:

CSS:

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

jQuery:

$('.map').width(555); // width of map canvas
user2385294
źródło
0

Nie podobało mi się, że mapa ładowała się dopiero po tym, jak ukryty element div stał się widoczny. Na przykład w karuzeli to nie działa.

To moje rozwiązanie polega na dodaniu klasy do ukrytego elementu, aby go odkryć i ukryć za pomocą pozycji bezwzględnej, a następnie wyrenderować mapę i usunąć klasę po załadowaniu mapy.

Przetestowano w Bootstrap Carousel.

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

źródło
0

użyj tej linii kodów, jeśli chcesz wyświetlić 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);
Ravi Darji
źródło
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
źródło
0

Pierwszy post. Mój element div googleMap znajdował się w elemencie div kontenera z {display: none} do momentu kliknięcia karty. Miał ten sam problem co OP. To zadziałało dla mnie:

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

Umieść ten kod w środku i na końcu kodu, w miejscu, w którym została kliknięta karta div kontenera, i odsłania ukryty element div. Ważną rzeczą jest to, że element div kontenera musi być widoczny przed wywołaniem inicjalizacji.

Wypróbowałem szereg rozwiązań proponowanych tutaj i na innych stronach i nie działały one dla mnie. Daj mi znać, jeśli to zadziała. Dzięki.

Leonard
źródło
0

Dodaj ten kod przed div lub przekaż go do pliku 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>

To zdarzenie zostanie wywołane po załadowaniu div, więc odświeży zawartość mapy bez konieczności naciskania F5

Balibrera
źródło
0

Po wyświetleniu mapy geokoduję adres, a następnie ustawiam środek mapy. U google.maps.event.trigger(map, 'resize');mnie nie działa.

Musiałem użyć map.setZoom(14);

Kod poniżej:

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

            }
        });
Andrzej
źródło
-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>

user6414609
źródło