Карты Google - масштабирование до размеров маркеров не работает, когда карта не видна

Я использую Google Maps API v2. Я добавляю маркеры на карту, а затем масштабирую, чтобы они соответствовали этим маркерам. Это отлично работает, если карта видна, я делаю это. Но если нет - например, если у меня есть полоса вкладок, а вкладка карты не выбрана при загрузке страницы - тогда, когда я показываю карту, уровень масштабирования и центр неверны.

Вот простой тестовый пример (использует jQuery):

<script type="text/javascript">

    var scale = Math.random() * 20;

    $(document).ready(function() {
        var $container = $('#container');
        // $container.hide();
        var map = new GMap2($('#map')[0]);
        $container.show();
        var markerBounds = new GLatLngBounds();
        for (var i = 0; i < 10; i++) {
            var randomPoint = new GLatLng(38.935394 + (Math.random() - 0.5) * scale, -77.061382 + (Math.random() - 0.5) * scale);
            map.addOverlay(new GMarker(randomPoint));
            markerBounds.extend(randomPoint);
        }
        map.setCenter(markerBounds.getCenter(), map.getBoundsZoomLevel(markerBounds));
    });

</script>

<div id="container">
    <div id="map" style="margin: 100px; width: 450px; height: 300px;"></div>
</div>

Это прекрасно работает, но если вы раскомментируете $container.hide(), все будет уничтожено.

Есть ли способ заставить API Карт Google правильно работать с невидимым элементом div?


person Herb Caudill    schedule 27.02.2010    source источник
comment
getBounds (вызывается в getBoundsZoomLevel) возвращает видимую область карты, поэтому я предполагаю, что вам придется масштабировать, чтобы соответствовать событию щелчка на вкладке. Краткое изложение метода в v3 лучше, чем описание в v2: v3 Возвращает границы широты/долготы текущего окна просмотра. Если карта еще не инициализирована (т. е. тип карты по-прежнему равен нулю) или центр и масштаб не установлены, результат будет нулевым. Я не думаю, что getBounds сильно изменился между версиями.   -  person Jim Schubert    schedule 27.02.2010


Ответы (2)


Все, что вам нужно сделать, это создать GMaps2() прежде всего. Затем вы можете hide() контейнер, добавить точки, получить getBoundsZoomLevel(), снова show(), и все должно работать нормально.

Попробуйте следующее:

$(document).ready(function() {
   var $container = $('#container');

   // First create the Map.
   var map = new GMap2($('#map')[0]);

   // The container can be hidden immediately afterwards.
   $container.hide();

   // Now you can do whatever you like!
   var markerBounds = new GLatLngBounds();
   for (var i = 0; i < 10; i++) {
      var randomPoint = new GLatLng( 38.935394 + (Math.random() - 0.5) * scale, 
                                    -77.061382 + (Math.random() - 0.5) * scale);
      map.addOverlay(new GMarker(randomPoint));
      markerBounds.extend(randomPoint);
   }
   map.setCenter(markerBounds.getCenter(), map.getBoundsZoomLevel(markerBounds));

   // Finally unhide the container.
   $container.show();
});

getBoundsZoomLevel

person Daniel Vassallo    schedule 28.02.2010
comment
Вы правы, это работает. Однако мой способ работы с вкладками заключается в том, что все скрыто при загрузке (с помощью CSS), а затем отображается правильная вкладка. В противном случае был бы короткий период, в течение которого все вкладки видны. Поэтому, если это вообще возможно, я хотел бы найти способ создать GMap2 в div, пока он еще скрыт. - person Herb Caudill; 28.02.2010
comment
@Herb: К сожалению, похоже, что GMap2 не создан должным образом, а для div сопоставления установлено значение display: none. Если вы выполните поиск в google для getBoundsZoomLevel, возвращающего 0, вы найдете несколько связанных историй. Я думаю, что вам лучше всего обойти эту проблему, настроив работу ваших вкладок... Я не знаю, может ли это помочь, но если вы скроете карту с помощью $container.css('visibility', 'hidden');, вы можете потом вызвать GMap2(), и это сработает. хорошо, когда вы возобновляете видимость с помощью $container.css('visibility', 'visible');. - person Daniel Vassallo; 28.02.2010
comment
Спасибо. Это очень полезно. Разница между display:none и visibility:hidden интересна - я раньше этого не понимал. Не получится использовать свойство видимости, чтобы скрыть вкладки, так как элементы с visibility:hidden все равно занимают место на странице. - person Herb Caudill; 28.02.2010

Вот что я в итоге сделал, для чего это стоит.

            $(".TabPanel").watch("display,visibility", function() {
                $(".MapContainer", this).each(function() {
                    if ($(this).is(":visible") == true) {
                        $(this).zoomToFitMarkers();
                    };
                });
            });

При этом используется плагин мониторинга Рика Страла для jQuery, чтобы отслеживать панель вкладок для изменяется видимость, а затем повторно применяется логика масштабирования.

Для полноты вот мое расширение zoomToFitMarkers:

$.fn.zoomToFitMarkers = function() {
    var map = this[0];
    map.gmap.checkResize();
    map.bounds = new GLatLngBounds();
    if (!!map.gmap.getOverlays) {
        for (i = 0; i < map.gmap.getOverlays.length; i++) {
            map.bounds.extend(map.gmap.getOverlays[i].getLatLng());
        }
        if (map.bounds && !map.bounds.isEmpty()) {
            var zoomLevel = map.gmap.getBoundsZoomLevel(map.bounds);
            zoomLevel = zoomLevel > 9 ? 9 : zoomLevel;
            zoomLevel = zoomLevel < 2 ? 2 : zoomLevel;
            map.gmap.setCenter(map.bounds.getCenter(), zoomLevel);
        }
    }
    map.gmap.checkResize();
};

Это зависит от нескольких соглашений:

  1. Объект GMap2 хранится в map.gmap, где map — целевой элемент DOM:

    var map= $("div#MapTarget")[0];
    map.gmap = new google.maps.Map2(map);
    
  2. Каждый раз, когда маркер добавляется на карту, он сохраняется в массиве для будущего использования:

    var marker = new GMarker(point);
    map.gmap.addOverlay(marker);
    // Keep track of new marker in getOverlays array
    if (!map.gmap.getOverlays) map.gmap.getOverlays = new Array();
    map.gmap.getOverlays.push(marker);
    
person Herb Caudill    schedule 28.02.2010