我正在使用 Google Maps API v3 在网站上创建内联 map 。在它的容器元素中,我还有一个绝对定位的叠加层,它显示了一些详细信息,视觉上悬停在 map 上。根据上下文确定该元素可能会增长到整个 map 元素的大小。
所有这些都工作正常,但是 Maps 实例当然仍然认为 map 的重叠部分是 map 的有效可用部分。这意味着,尤其是当叠加层处于最大高度时,setCenter
不会关注可见中心,并且使用 DirectionsRenderer
绘制的路线是部分位于覆盖层下方。
看这张图:
有没有办法将实际视口(viewport)限制在蓝色区域,以便setCenter
以箭头尖端为中心,setBounds
适合蓝色部分?
最佳答案
我目前已经设法实现了一个可接受的功能解决方法。
一些重要的注意事项:
- 每个
Map
对象都有一个Projection
,可以将 LatLng 点转换为 map 点。 Projection
用于计算的 map 点位于“世界”坐标中,这意味着它们是缩放级别为 0 的世界地图上的像素。- 每个缩放级别都使显示的像素数恰好加倍。这意味着给定 map 点中的像素数等于
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 map 在适应边界时在内部使用未知边距,因此没有可靠的方法来预测所需的缩放级别。
因此,一个可能的解决方案是调用两步火箭。首先,对整个 map 调用 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 像素宽的边栏进行校正。
在某些情况下,这可能会导致轻微的动画异常,但在实践中,我只看到这种情况发生在真正垃圾点击按钮导致适合操作时。否则它运行得很好。
希望这对某人有帮助:)
关于javascript - 从 Google map 视口(viewport)边界中排除重叠元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21913116/