Làm thế nào để đối phó với google map bên trong một div ẩn (Ảnh cập nhật)


127

Tôi có một trang và bản đồ google nằm trong một div ẩn lúc đầu. Sau đó tôi hiển thị div sau khi tôi nhấp vào một liên kết nhưng chỉ phía trên bên trái của bản đồ hiển thị.

tôi đã thử chạy mã này sau khi nhấp chuột:

    map0.onResize();

hoặc là:

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

bất kỳ ý tưởng. đây là hình ảnh của những gì tôi thấy sau khi hiển thị div với bản đồ ẩn trong đó.văn bản thay thế


Đã có một số câu hỏi về SO về vấn đề này, bao gồm hiển thị bản đồ Google từ một khu vực ẩn
Matt Ball

@Matt Ball - như đã cập nhật, tôi đã thử thêm sự kiện thay đổi kích thước ở đó nhưng vẫn không hoạt động
leora

@Matt Ball - Tôi đã làm điều này để làm việc. Sau khi tôi tạo đối tượng google map, tôi lưu trữ nó trong một biến toàn cục để tôi có thể tham chiếu lại nó sau và gọi thay đổi kích thước bây giờ có vẻ hiệu quả. Tôi đang cố gắng không phải tạo lại đối tượng bản đồ mỗi lần tôi hiển thị vì tôi cho phép mọi người chuyển đổi qua lại.
leora

@ooo rất đơn giản với đoạn mã dưới đây. Tất cả những gì bạn cần thêm là một điều kiện if để kiểm tra xem đối tượng bản đồ đã được khởi tạo hay chưa. Đây là một mã số được viết để giải quyết vấn đề ban đầu của bạn, đó là tải bản đồ một cách chính xác.
Vui vẻ

@philar - yup. . cảm ơn ở đây . do đó, upvote :). Dù bằng cách nào tôi cũng cần lưu trữ các biến ở cấp độ toàn cầu để tránh tái khởi động lại
leora

Câu trả lời:


103

Chỉ cần tự mình kiểm tra và đây là cách tôi tiếp cận nó. Khá thẳng về phía trước, cho tôi biết nếu bạn cần làm rõ

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>

Vì vậy, về cơ bản bạn chỉ khởi tạo bản đồ khi div được hiển thị? Có cách nào để làm điều này để đối tượng bản đồ chỉ được khởi tạo một lần (khi tải trang) không?
lucas

1
Tôi cũng có thể đề xuất độ trễ setTimeout để gọi hàm thứ hai nếu bạn đang gọi một chương trình () để cho phép thời gian thay đổi kích thước.
Eric.18

126

Tôi đã có cùng một vấn đề và phát hiện ra rằng khi hiển thị div, hãy gọi google.maps.event.trigger(map, 'resize');và nó xuất hiện để giải quyết vấn đề cho tôi.


64
Để giữ trung tâm ban đầu của bản đồ ngay sau khi thay đổi kích thước, hãy xem xét mở rộng câu lệnh thay đổi kích thước theo cách này: var centre = map.getCenter (); google.maps.event.trigger (bản đồ, 'thay đổi kích thước'); map.setCenter (giữa);
John Doppelmann

10
Không chắc chắn tại sao, nhưng tôi cần bọc giải pháp bên trong setTimeout nhỏ để làm cho nó hoạt động: setTimeout (function () {google.maps.event.trigger (map, 'resize')}, 100);
HoffZ

@JohnDoppelmann Cảm ơn vì tiền boa! Nó không trực quan tại sao nó không duy trì trung tâm, cũng như làm thế nào để buộc nó trở lại.

Đặt trung tâm bản đồ và mức thu phóng lại sau khi kích hoạt sự kiện 'thay đổi kích thước'. Để biết thêm thông tin, hãy xem: code.google.com/p/gmaps-api-issues/issues/detail?id=1448
ruhong

@HoffZ điều này có thể là do mã thay đổi kích thước của bạn bắn trước khi có hiệu lực hiển thị, thời gian chờ sẽ trì hoãn cho đến khi chương trình được thực hiện, sau đó thay đổi kích thước có thể làm cho nó hoạt động. Bạn có thể có thể đạt được hiệu ứng tương tự khi thay đổi thứ tự thực thi mã của mình để đảm bảo rằng khi thực hiện sự kiện, hiển thị div được thực thi trước khi thay đổi kích thước bản đồ.
Bardo

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

Nếu bạn không có sẵn bản đồ biến, thì đó phải là yếu tố đầu tiên (trừ khi bạn làm điều gì đó ngu ngốc) trong divđó có chứa GMAP.


Bạn có chắc chắn rằng bạn có thể kích hoạt phần tử trên div thay vì đối tượng google.map.Map không?
Salman A

@SalmanA - Chỉ cần kiểm tra cái này và nó hoạt động với tôi (mặc dù Bản đồ dường như có một Trung tâm mới). Từ nghiên cứu trước đây, tôi không biết điều này có thể xảy ra với CSN
Hal

CS N ... Điều này làm việc cho tôi, nhưng, nó để vị trí trung tâm ở sai vị trí. Bản đồ của tôi đang khởi tạo giống như ảnh chụp màn hình của OP và nó giống như trung tâm: nằm ở góc trên cùng bên trái của map_canvas của tôi. Suy nghĩ làm thế nào để có được nó để vẽ trung tâm?
Kirk Ross

13

Tôi đã có một bản đồ Google bên trong tab Bootstrap, không hiển thị chính xác. Đây là sửa chữa của tôi.

// 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
Tôi đã phải thay thế 'hiển thị' thành 'hiển thị.bs.tab' để làm việc này cho bản đồ bị ẩn trong tab không hoạt động. Cảm ơn
Nicola

Tôi đang sử dụng SmartWizard 4 và đây là giải pháp duy nhất hiệu quả với tôi và nó hoạt động rất tốt! Tôi đã đổi 'a[href="#profileTab"]'thành step-2tên của DIV chứa bản đồ DIV.
GeospatialPython.com

7

Cách làm mới bản đồ khi bạn thay đổi kích thước div

Chỉ gọi là không đủ google.maps.event.trigger(map, 'resize');Bạn cũng nên đặt lại trung tâm bản đồ.

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

Làm thế nào để lắng nghe sự kiện thay đổi kích thước

Angular (ng-show hoặc ui-bootstrap sụp đổ)

Liên kết trực tiếp với khả năng hiển thị của phần tử thay vì giá trị được liên kết với ng-show, bởi vì đồng hồ $ có thể kích hoạt trước khi ng-show được cập nhật (vì vậy div sẽ vẫn ở chế độ ẩn).

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

jQuery .show ()

Sử dụng gọi lại tích hợp

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

Bootstrap 3 phương thức

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

Phương pháp thay đổi kích thước phương thức bootstrap 3 của bạn đã khắc phục vấn đề của tôi một cách hoàn hảo trong khi hầu hết các đề xuất khác thì không. Cảm ơn!
BrianLegg

6

Nếu bạn có Google Map được chèn bằng cách sao chép / dán mã iframe và bạn không muốn sử dụng Google Maps API , đây là một giải pháp dễ dàng. Chỉ cần thực hiện dòng javascript sau khi bạn hiển thị bản đồ ẩn. Nó chỉ lấy mã HTML iframe và chèn nó vào cùng một vị trí, do đó, nó sẽ hiển thị lại:

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

Phiên bản jQuery:

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

HTML:

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

Ví dụ sau hoạt động cho một bản đồ ban đầu được ẩn trong tab 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
Giải pháp tốt nhất cho bất kỳ ai không tải Google Map JS mà chỉ cần sử dụng iframe với src urlhttps://www.google.com/maps/embed/v1/place?..
gsinha

6

Cũng có thể chỉ kích hoạt sự kiện thay đổi kích thước cửa sổ gốc.

Google Maps sẽ tự động tải lại:

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

5

Tôi có cùng một vấn đề, google.maps.event.trigger(map, 'resize')đã không làm việc cho tôi.

Những gì tôi đã làm là đặt một bộ đếm thời gian để cập nhật bản đồ sau khi hiển thị 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(....
    ....
}

Tôi không biết nếu đó là cách thuận tiện hơn để làm điều đó nhưng nó hoạt động!


sử dụng setTimeout để đợi một lần.
Joe Austin

4

Với jQuery bạn có thể làm một cái gì đó như thế này. Điều này giúp tôi tải Google Map trong Umbraco CMS trên một tab không thể nhìn thấy ngay lập tức.

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

waitForVisibleMapElement();

Đây là giải pháp duy nhất hiệu quả với tôi và vấn đề của tôi. Tôi đã có một bản đồ google bên trong tab Materialize.CSS không hiển thị bản đồ, nhưng chỉ hiển thị nền màu xám chỉ có biểu tượng Marker và Google ở ​​góc bên trái. Tôi đặt div nội dung tab để khởi tạo bản đồ khi hiển thị và nó hoạt động hoàn hảo. Ví dụ
Gorgon_Union

3

Giải pháp của tôi rất đơn giản và hiệu quả:

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

Tôi đoán câu hỏi ban đầu là với một bản đồ được initalized trong một div ẩn của trang. Tôi đã giải quyết một vấn đề tương tự bằng cách thay đổi kích thước bản đồ trong div ẩn khi tài liệu sẵn sàng, sau khi nó được khởi tạo, bất kể trạng thái hiển thị của nó. Trong trường hợp của tôi, tôi có 2 bản đồ, một bản đồ được hiển thị và một bản đồ bị ẩn khi chúng được khởi tạo và tôi không muốn khởi tạo bản đồ mỗi khi nó được hiển thị. Đây là một bài viết cũ, nhưng tôi hy vọng nó sẽ giúp bất cứ ai đang tìm kiếm.


2

Tôi đã tìm thấy cái này để làm việc cho tôi:

trốn:

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

để hiển thị:

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

2

Nếu được sử dụng bên trong các tab Bootstrap v3, các thao tác sau sẽ hoạt động:

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

nơi tab-locationlà ID của tab chứa đồ.


2

Giống như John Doppelmann và HoffZ đã chỉ ra, hãy đặt tất cả các mã lại với nhau như sau trong chức năng hiển thị div hoặc sự kiện onclick của bạn:

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

Nó làm việc hoàn hảo cho tôi


0

Giải pháp của tôi là:

CSS:

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

jQuery:

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

0

Tôi không thích rằng bản đồ sẽ chỉ tải sau khi div ẩn đã hiển thị. Ví dụ, trong băng chuyền, điều đó không thực sự hiệu quả.

Giải pháp này của tôi là thêm lớp vào thành phần ẩn để bỏ ẩn nó và ẩn nó với vị trí tuyệt đối thay vào đó, sau đó hiển thị bản đồ và xóa lớp sau khi tải bản đồ.

Đã thử nghiệm trong Bootstrap Carousel.

HTML

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

CSS

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

Mã não

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

0

sử dụng dòng mã này khi bạn muốn hiển thị bản đồ.

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

Bài viết đầu tiên. Div googleMap của tôi nằm trong div div container với {display: none} cho đến khi tab được nhấp. Có vấn đề tương tự như OP. Điều này làm việc cho tôi:

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

Dán mã này vào bên trong và ở cuối mã của bạn, nơi tab div container của bạn được nhấp và hiển thị div ẩn của bạn. Điều quan trọng là div container của bạn phải được hiển thị trước khi khởi tạo có thể được gọi.

Tôi đã thử một số giải pháp được đề xuất ở đây và các trang khác và chúng không hiệu quả với tôi. Hãy cho tôi biết, nếu việc này giúp ích cho bạn. Cảm ơn.


0

Thêm mã này trước div hoặc chuyển nó vào tệp 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>

Sự kiện này sẽ được kích hoạt sau khi tải div, vì vậy nó sẽ làm mới nội dung bản đồ mà không cần phải nhấn F5


0

Khi hiển thị bản đồ, tôi đang mã hóa địa chỉ rồi đặt trung tâm bản đồ. Việc google.maps.event.trigger(map, 'resize');này không hiệu quả với tôi.

Tôi đã phải sử dụng một map.setZoom(14);

Mã dưới đây:

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>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.