简体   繁体   English

显示Infowindow后阻止Google地图移动

[英]Preventing Google Maps Move After Displaying Infowindow

I'm trying to display a infowindow on a Google Maps. 我正在尝试在Google地图上显示信息窗口。 It displays perfect, when you hover over a marker it loads up a infowindow but the map jumps to fit in the window. 它显示完美,当你将鼠标悬停在标记上时,它会加载一个信息窗,但是地图会跳转到适合窗口的状态。 I don't want the map to move but rather infowindow set its position according to map. 我不希望地图移动,而是根据地图设置其位置。 Booking.com has something like this. Booking.com有类似的东西。

EDIT: Added my code 编辑:添加了我的代码

Here is the stripped down version of my code. 这是我的代码的精简版本。 I'm getting all the info from an AJAX service and this service returns response (which holds some more info too). 我从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;
            });
        }
    }
});

As you can see below, the first image shows the infowindow displayed at bottom of marker while second one shows the infowindow displayed on top of the marker. 如下所示,第一张图像显示标记底部显示的信息窗口,而第二张图像显示标记顶部显示的信息窗口。 The map doesn't move but infowindow sets its position within the boundries of the map. 地图不会移动,但infowindow会将其位置设置在地图的边界内。

Infowindow底部的标记Infowindow在标记之上

In your declaration for setting the info window options infowindow.setOptions , add the following option to disable the panning of the map when the infowindow is displayed, disableAutoPan : true . 在设置信息窗口选项infowindow.setOptions声明中,添加以下选项以在显示disableAutoPan : true时禁用地图平移, disableAutoPan : true

However this will also mean you'll need to calculate the real estate you have available to display the infowindow on your map and give it a position using the position option. 但是,这也意味着您需要计算您可用的房地产,以便在地图上显示信息窗口,并使用position选项给它一个位置。 Otherwise it won't be guaranteed that your infowindow will be completely visible on the map. 否则,将无法保证您的信息窗口在地图上完全可见。

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

EDIT: How to calculate screen real estate 编辑: 如何计算屏幕房地产

I realize I was pretty vague with my suggestion to calculate the screen real estate available to set the position of your infowindow, when part of your question was to actually set the infowindow's position. 我意识到,当我的部分问题是实际设置infowindow的位置时,我的建议是计算可用于设置信息窗口位置的屏幕空间。 So I've provided an update to my answer on how you can calculate the screen real estate and adjust your infowindow's position. 所以我已经提供了一个更新我的答案,你可以如何计算屏幕空间并调整你的infowindow的位置。

The key is to first convert your points from LatLng to pixels, and find out the pixel coordinate of the marker on the map with relation to the pixel coordinate of the map's center. 关键是首先将您的点从LatLng转换为像素,然后找出地图上标记的像素坐标与地图中心的像素坐标的关系。 The following snippet demonstrates how this can be done. 以下代码段演示了如何完成此操作。

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

Once you've got your pixel coordinates, you'll need to find out which quadrant of the map canvas the marker is currently residing in. This is achieved by comparing the X and Y coordinates of the marker to the map, like so: 获得像素坐标后,您需要找出标记当前所在的地图画布的哪个象限。这是通过将标记的X和Y坐标与地图进行比较来实现的,如下所示:

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

Here, I'm determining if the point is in the bottom right, bottom left, top right or top left quadrant of the map based on it's relative position to the map's center. 在这里,我根据它与地图中心的相对位置确定该点是位于地图的右下角,左下角,右上角还是左上角。 Keep in mind this is why we use pixels as opposed to LatLng values, because LatLng values will always yield the same result - but reality is the marker can be in any quadrant of the map canvas depending on panning. 请记住,这就是我们使用像素而不是LatLng值的原因,因为LatLng值将始终产生相同的结果 - 但实际情况是标记可以位于地图画布的任何象限中,具体取决于平移。

Once you know which quadrant the marker is in, you can give offset values to the infowindow to position it so it's visible on the map - like so: 一旦你知道了标记所在的象限,就可以给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

Once the offset value is determined you can just adjust the pixelOffset of your infowindow on whatever listener you have invoking the infoWindow.open() method. 确定偏移值后,您可以在调用infoWindow.open()方法的任何侦听器上调整infoWindow.open()pixelOffset This is done by using the setOptions() method for infowindows: 这是通过对setOptions()使用setOptions()方法完成的:

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

Here is a working JSFiddle example of the solution described above. 这是上述解决方案的一个有效的JSFiddle示例

Note: You will notice the annoying "arrow" on the infowindow displaying desbite the position of your infowindow, this is part of the default Google Map's setting for infowindows and I could not find a proper way of getting rid of it. 注意:你会注意到infowindow上显示臭名昭着的“箭头”,显示你信息窗口的位置,这是默认谷歌地图设置信息窗口的一部分,我找不到一个正确的方法来摆脱它。 There was a suggestion here , but I couldn't get it to work. 有人建议在这里 ,但我无法得到它的工作。 Alternatively you can use the infobox library or the infobubble library - which gives you more styling options. 另外,您可以使用信息框库infobubble库 -它给你更多的时尚选择。

Suvi Vignarajah's answer is great, what I didn't like about it was how unpredictable the position of the window is near the edges. Suvi Vignarajah的答案很棒,我不喜欢的是窗户的位置靠近边缘是多么不可预测。

I tweaked it so that the bubble glues to the wall as it should be expected: http://jsfiddle.net/z5NaG/5/ 我调整它,以便泡沫胶粘到墙上,因为它应该是预期的: http//jsfiddle.net/z5NaG/5/

The only condition is that you need to know the width & height of the infoWindow, you can position it quite nicely. 唯一的条件是你需要知道infoWindow的widthheight ,你可以很好地定位它。 You would work it out through the maps' pixels. 你可以通过地图的像素来解决它。 If you don't know it you could initialize the InfoWindow offscreen, get it's size and proceed opening it again at the right spot. 如果您不知道它,您可以在屏幕外初始化InfoWindow,获取它的大小并在正确的位置再次打开它。 Ugly but would work. 丑陋但会工作。

First initialize on overlay at time of map initialization by running this function: 首先通过运行此函数在映射初始化时初始化叠加:

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

Then at open event adjust the offset like so: 然后在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);

},

And the result is pretty nice, but this triangle seems out of place now. 结果非常好,但这个三角形现在似乎不合适。

You can use InfoBox to remove the pointy arrow on bottom: 您可以使用InfoBox删除底部的尖箭头:

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

and style the bubble with the following code: 并使用以下代码设置气泡样式:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM