18

我正在尝试在 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 会在地图边界内设置其位置。

标记的信息窗口底部 标记顶部的信息窗口

4

2 回答 2

43

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

但是,这也意味着您需要计算可用于在地图上显示信息窗口的空间,并使用该position选项为其指定位置。否则无法保证您的信息窗口在地图上完全可见。

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

编辑:如何计算屏幕空间

我意识到我对计算可用于设置信息窗口位置的屏幕空间的建议非常模糊,而您的问题的一部分是实际设置信息窗口的位置。因此,我提供了有关如何计算屏幕空间和调整信息窗口位置的答案的更新。

关键是首先将您的点从 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 值将始终产生相同的结果 - 但现实是标记可以位于地图画布的任何象限中,具体取决于平移。

一旦您知道标记位于哪个象限,您就可以为信息窗口提供偏移值以定位它,使其在地图上可见 - 如下所示:

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.open()这是通过使用setOptions()infowindows 的方法完成的:

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

这是上述解决方案的有效JSFiddle 示例。

注意:您会注意到信息窗口上令人讨厌的“箭头”显示您的信息窗口的位置,这是默认谷歌地图信息窗口设置的一部分,我找不到摆脱它的正确方法。这里有一个建议,但我无法让它发挥作用。或者,您可以使用infoboxinfobubble 库- 它为您提供更多样式选项。

于 2013-08-23T19:23:48.623 回答
1

Suvi Vignarajah 的回答很棒,我不喜欢它是窗户的位置在边缘附近是多么不可预测。

我对其进行了调整,使气泡像预期的那样粘在墙上:http: //jsfiddle.net/z5NaG/5/

唯一的条件是你需要知道infoWindow的width& 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;
}
于 2014-02-04T21:51:06.827 回答