Предотвращение Перемещения Карт Google После Отображения Infowindow

Я пытаюсь отобразить infowindow на картах Google. Он отображает perfect, когда вы наводите курсор на маркер, он загружает infowindow, но карта прыгает, чтобы поместиться в окне. Я не хочу, чтобы карта перемещалась, а скорее infowindow установил ее положение в соответствии с картой. Booking.com есть что-то вроде этого.

EDIT: добавил мой код

вот урезанная версия моего кода. Я получаю всю информацию от служба AJAX и этот сервис возвращает response (который также содержит дополнительную информацию).

$.ajax({
    url: 'URL',
    dataType: "json",
    type: "GET",
    success: function(response) {
        // delete all markers
        clearOverlays();

        var infowindow = new google.maps.InfoWindow();

        for (var i = 0; i < response.length; i++) {
            item = response[i];

            var marker = new google.maps.Marker({
                position: new google.maps.LatLng(item.lat, item.lng),
                map: map,
                url: item.detail_url
            });

            markersArray.push(marker);

            // display infowindow
            google.maps.event.addListener(marker, "mouseover", (function(marker, item) {
                return function() {
                    infowindow.setOptions({
                        content: 'SOME CONTENT HERE FOR INFOWINDOW'
                    });

                    infowindow.open(map, marker);
                }
            })(marker, item));

            // remove infowindow
            google.maps.event.addListener(marker, 'mouseout', function() {
                infowindow.close();
            });

            // marker click
            google.maps.event.addListener(marker, 'click', function() {
                window.location.href = marker.url;
            });
        }
    }
});

Как вы можете видеть ниже, первое изображение показывает infowindow отображается в нижней части маркера, а второй показывает infowindow отображается в верхней части маркера. Карта не перемещается, но infowindow устанавливает свое положение в пределах границ карты.

Infowindow bottom of markerInfowindow on top of marker

2 ответов


в вашей декларации для установки параметров информационного окна infowindow.setOptions, добавьте следующую опцию, чтобы отключить панорамирование карты при отображении infowindow,disableAutoPan : true.

однако это также будет означать, что вам нужно будет рассчитать недвижимость, которую вы имеете в распоряжении, чтобы отобразить infowindow на вашей карте и дать ему позицию с помощью . В противном случае не будет гарантировано, что ваше infowindow будет полностью видимым на карта.

https://developers.google.com/maps/documentation/javascript/reference#InfoWindowOptions

EDIT:Как рассчитать экран недвижимости

Я понимаю, что я был довольно расплывчатым с моим предложением рассчитать экранную недвижимость, доступную для установки позиции вашего infowindow, когда часть вашего вопроса заключалась в том, чтобы фактически установить позицию infowindow. Так что я обновление моего ответа на как вы можете рассчитать экран недвижимости и настроить положение вашего infowindow.

ключ состоит в том, чтобы сначала преобразовать ваши точки из LatLng в пиксели и узнать пиксельную координату маркера на карте по отношению к пиксельной координате центра карты. Следующий фрагмент демонстрирует, как это можно сделать.

getPixelFromLatLng: function (latLng) {
    var projection = this.map.getProjection();
    //refer to the google.maps.Projection object in the Maps API reference
    var point = projection.fromLatLngToPoint(latLng);
    return point;
}

как только вы получите свои пиксельные координаты, вам нужно будет узнать, какой квадрант карты canvas маркер в настоящее время проживающего в. Это достигается путем сравнения координат X и Y маркера с картой, например:

quadrant += (point.y > center.y) ? "b" : "t";
quadrant += (point.x < center.x) ? "l" : "r";

здесь я определяю, находится ли точка в нижнем правом, нижнем левом, верхнем правом или верхнем левом квадранте карты на основе ее относительного положения к центру карты. Имейте в виду, что именно поэтому мы используем пиксели в отличие от значений LatLng, потому что значения LatLng всегда будут давать один и тот же результат - но реальность такова, что маркер может быть в любом квадранте холста карты в зависимости от сдвига.

как только вы узнаете, в каком квадранте находится маркер, вы можете дать значения смещения infowindow, чтобы расположить его так, чтобы он был виден на карте-например:

if (quadrant == "tr") {
    offset = new google.maps.Size(-70, 185);
} else if (quadrant == "tl") {
    offset = new google.maps.Size(70, 185);
} else if (quadrant == "br") {
    offset = new google.maps.Size(-70, 20);
} else if (quadrant == "bl") {
    offset = new google.maps.Size(70, 20);
}
//these values are subject to change based on map canvas size, infowindow size

как только значение смещения определено, вы можете просто настроить pixelOffset вашего infowindow на любом слушателе, которого вы вызываете infoWindow.open() метод. Это делается с помощью setOptions() метод infowindows:

infowindow.setOptions({pixelOffset : self.getInfowindowOffset(self.map, marker)}); 

вот работает JSFiddle пример решения, описанного выше.

Примечание: вы заметите раздражающую "стрелку" на infowindow, отображающую desbite положение вашего infowindow, это часть настройки карты Google по умолчанию для infowindows, и я не мог найти правильный способ избавиться от него. Было предложение здесь, но я не мог заставить его работать. В качестве альтернативы вы можете использовать библиотека infobox или infobubble библиотека - что дает вам больше вариантов стиля.


ответ Суви Виньяраджи отличный, что мне не понравилось, так это то, насколько непредсказуемо положение окна вблизи краев.

Я настроил его так, что пузырь приклеивается к стене, как и следовало ожидать:http://jsfiddle.net/z5NaG/5/

единственное условие заключается в том, что вы должны знать width & height из infoWindow, вы можете расположить его довольно красиво. Вы бы поняли это через пиксели карт. Если вы не знаете, что вы могли инициализируйте InfoWindow за пределами экрана, получите его размер и продолжайте открывать его снова в нужном месте. Некрасиво, но сработает.

сначала инициализируйте наложение во время инициализации карты, запустив эту функцию:

    ourOverlay:null,
    createOverlay:function(){
        this.ourOverlay = new google.maps.OverlayView();
        this.ourOverlay.draw = function() {};
        this.ourOverlay.setMap(this.map);
    },

затем на open событие отрегулируйте смещение так:

getInfowindowOffset: function (map, marker) {
    // Settings
    var iwWidth = 240; // InfoWindow width 
    var iwHeight = 190; // InfoWindow Height
    var xOffset = 0;
    var yOffset = 0;

    // Our point of interest
    var location = this.ourOverlay.getProjection().fromLatLngToContainerPixel(marker.getPosition()); 

    // Get Edges of map in pixels: Sout West corner and North East corner
    var swp = this.ourOverlay.getProjection().fromLatLngToContainerPixel(map.getBounds().getSouthWest()); 
    var nep = this.ourOverlay.getProjection().fromLatLngToContainerPixel(map.getBounds().getNorthEast()); 

    // Horizontal Adjustment
    if(location.x<iwWidth/2){
        xOffset= iwWidth/2-location.x;
    }else if(location.x>nep.x-iwWidth/2){
        xOffset = (nep.x-iwWidth/2)-location.x ;
    }

    // Vertical Adjustment
    if(location.y<iwHeight){
        yOffset = location.y + iwHeight-(location.y-nep.y);
    }

    // Return it
    return new google.maps.Size(xOffset, yOffset);

},

и результат довольно приятный, но этот треугольник кажется неуместным сейчас.

можно использовать InfoBox чтобы удалить заостренную стрелку на дно:

            GmapsManager.infowindow = new InfoBox({
            content:'',
            alignBottom: true,
            closeBoxURL: "",
        });

и стиль пузырь со следующим кодом:

.infobox-popup{
    background: #fff;
    -webkit-border-radius: 3px;
    border-radius: 3px;
    padding: 5px;
    margin-left: -100px;
    margin-bottom: 30px;
    width: 200px;
    -webkit-box-shadow: 0 0 1px 0 #595959;
    box-shadow: 0 0 1px 0 #595959;
}