显示Infowindow后阻止Google地图移动

时间:2013-08-23 14:10:52

标签: javascript google-maps google-maps-api-3 infowindow

我正在尝试在Google地图上显示信息窗口。它显示完美,当你将鼠标悬停在标记上时,它会加载一个信息窗,但是地图会跳转到适合窗口的状态。我不希望地图移动,而是根据地图设置其位置。 Booking.com有这样的东西。

编辑:添加了我的代码

这是我的代码的精简版本。我从 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 bottom of marker Infowindow on top of marker

2 个答案:

答案 0 :(得分:37)

在设置信息窗口选项infowindow.setOptions的声明中,添加以下选项以在显示信息窗时disableAutoPan : true禁用地图平移。

但是,这也意味着您需要计算可用的房地产,以便在地图上显示信息窗口,并使用position选项为其提供一个位置。否则,将无法保证您的信息窗口在地图上完全可见。

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

编辑:如何计算屏幕空间

我意识到,当我的部分问题是要实际设置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;
}

获得像素坐标后,您需要找出标记当前所在的地图画布的哪个象限。这是通过将标记的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()。这是通过对infowindows使用setOptions()方法完成的:

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

这是上述解决方案的工作JSFiddle example

注意:你会注意到infowindow上显示臭名昭着的“箭头”,显示你信息窗口的位置,这是默认Google Map的infowindows设置的一部分,我找不到合适的方法摆脱它。有一个建议here,但我无法让它发挥作用。或者,您可以使用infobox libraryinfobubble library - 这可以为您提供更多样式选项。

答案 1 :(得分:1)

Suvi Vignarajah的答案很棒,我不喜欢的是窗户的位置靠近边缘是多么难以预测。

我调整了它,以便气泡粘在墙上,应该是预期的:http://jsfiddle.net/z5NaG/5/

唯一的条件是你需要知道width&amp; infoWindow的height,你可以很好地定位它。你可以通过地图的像素来解决它。如果您不知道它,您可以在屏幕外初始化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;
}