我暂时已经设法实现了一个可接受的功能解决方法。
一些值得了解的一般注意事项:
- 每个
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 像素宽的侧边栏。
在某些情况下,这可能会导致轻微的动画偏离,但在实践中,我只在真正垃圾点击按钮导致适合操作时才看到这种情况。否则它运行得非常好。
希望这可以帮助某人:)