【问题标题】:Exclude overlaid element from Google Maps viewport bounds从 Google 地图视口范围中排除叠加元素
【发布时间】:2014-02-20 16:02:30
【问题描述】:

我正在使用 Google Maps API v3 在网站上创建内嵌地图。在它的容器元素中,我还有一个绝对定位的叠加层,它显示了一些详细信息,视觉上悬停在地图上。根据上下文确定此元素可能会增长到整个地图元素的大小。

这一切都很好,但是 Maps 实例当然仍然认为地图的覆盖部分是地图的有效可用部分。这意味着,尤其是当叠加层处于最大高度时,setCenter 不会关注 可见 中心,并且使用 DirectionsRenderer 绘制的路线部分位于叠加层下方。

看这张图片:

有没有办法将实际视口限制在蓝色区域,以便setCenter 以箭头为中心,setBounds 适合蓝色部分?

【问题讨论】:

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


    【解决方案1】:

    我暂时已经设法实现了一个可接受的功能解决方法。

    一些值得了解的一般注意事项:

    • 每个Map 对象都有一个Projection,可以在LatLng 点和地图点之间进行转换。
    • Projection 用于计算的地图点位于“世界”坐标中,这意味着它们是缩放级别为 0 时世界地图上的像素。
    • 每个缩放级别都会使显示的像素数量翻倍。这意味着给定地图点中的像素数等于2 ^ zoom

    下面的示例假定右侧有一个 300 像素宽的侧边栏 - 适应其他边框应该很容易。

    居中

    利用这些知识,编写一个用于偏心的自定义函数变得微不足道:

    function setCenter(latlng)
    {
        var z = Math.pow(2, map.getZoom());
        var pnt = map.getProjection().fromLatLngToPoint(latlng);
        map.setCenter(map.getProjection().fromPointToLatLng(
                        new google.maps.Point(pnt.x + 150/z, pnt.y)));
    }
    

    这里的关键位是z 变量,以及最后一行中的pnt.x + 150/z 计算。由于上述假设,这会将当前缩放级别的点移动到左侧 150 像素的中心,从而补偿右侧边栏上缺失的 300 像素。

    边界

    边界问题远没有那么微不足道。这样做的原因是要正确偏移点,您需要知道缩放级别。对于重新定位,这不会改变,但为了适应以前未知的界限,它几乎总是会改变。由于 Google 地图在适应边界时会在内部使用未知边距,因此没有可靠的方法来预测所需的缩放级别。

    因此,一个可能的解决方案是调用两步火箭。首先,用整个地图致电fitBounds。这应该使边界和缩放级别至少几乎正确。然后在此之后,再次调用fitBounds 修正侧边栏。

    应该使用LatLngBounds 对象作为参数调用以下示例实现,或者没有参数以默认为当前边界。

    function setBounds(bnd, cb)
    {
        var prj = map.getProjection();
        if(!bnd) bnd = map.getBounds();
        var ne = prj.fromLatLngToPoint(bnd.getNorthEast()),
            sw = prj.fromLatLngToPoint(bnd.getSouthWest());
        if(cb) ne.x += (300 / Math.pow(2, map.getZoom()));
        else google.maps.event.addListenerOnce(map,'bounds_changed',
            function(){setBounds(bnd,1)});
        map.fitBounds(new google.maps.LatLngBounds(
            prj.fromPointToLatLng(sw), prj.fromPointToLatLng(ne)));
    }
    

    我们首先在这里做的是获取边界的实际点,由于没有设置 cb,我们在 bounds_changed 上安装了一个一次性事件,然后在 fitBounds 完成后触发.这意味着在校正缩放后,该函数会自动第二次调用。第二次调用,使用cb=1,然后偏移框以校正 300 像素宽的侧边栏。

    在某些情况下,这可能会导致轻微的动画偏离,但在实践中,我只在真正垃圾点击按钮导致适合操作时才看到这种情况。否则它运行得非常好。

    希望这可以帮助某人:)

    【讨论】:

    • 嘿 Niels,我正在解决相同的问题,并遇到了您的解决方案。最后,它对你有用吗?你找到更好的东西了吗?
    • 我在omines.nl/contact 上实现了这个,今天它仍然可以正常工作:)
    【解决方案2】:

    您可以使用地图panBy() method,它允许您将地图的中心更改为给定距离(以像素为单位)。

    希望这会有所帮助!

    【讨论】:

    • 感谢您的回答,但之后平移并不是将路线放入较小区域的解决方案 - 它只会滚动到另一端。我正在寻找一种方法来限制视口本身而不阻止它在排除区域中绘制。
    • 对。我明白你的意思。这个问题已经在这里被问过几次,但从来没有一个可行的解决方案来回答。我建议提交feature request,因为我认为能够操纵“视口”大小会非常有用。
    • Done :) 另外,我已经设法创建了我现在正在测试的可行解决方法。
    • 我很想知道您想出了什么可行的解决方法
    • 嗯,我在我们的新公司网站上有一个工作示例,实际上将它撕成独立的将是一项艰巨的工作。这个周末我会考虑这样做:P
    【解决方案3】:

    我也有类似的需求,最后只是在 LatLngBounds 对象的东边强制了一些“填充”。

    从好的方面来说,它很简单而且很有效。不利的一面是,它并不是真正通用的。只是一个快速的小技巧。

    // start with a standard LatLngBounds object, extending as you usually would...
    bounds = new google.maps.LatLngBounds();
    
    // ...
    
    ne = bounds.getNorthEast();
    sw = bounds.getSouthWest();
    
    // the multiplier used to add space; positive for east, negative for west
    lngPadding = 1.5
    
    extendedLng = ne.lng() + (ne.lng() - sw.lng()) * lngPadding;
    
    // copy original and extend with the new Lng
    extendedBounds = bounds;
    extendedBounds.extend(new google.maps.LatLng(ne.lat(), extendedLng));
    
    map.fitBounds(extendedBounds);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-03
      • 2014-10-16
      相关资源
      最近更新 更多