谷歌地图 fitBounds 回调
Posted
技术标签:
【中文标题】谷歌地图 fitBounds 回调【英文标题】:google maps fitBounds callback 【发布时间】:2016-06-16 03:27:09 【问题描述】:我知道有一个bounds_changed
事件会在边界发生变化时触发,但是我需要知道 fitBounds 何时完成(当边界发生变化或边界保持不变时)。
Google 有某种容忍度,如果边界变化很小,它实际上不会改变边界/调用 bounds_changed。我需要知道什么时候会发生这种情况。
我已经通过超时成功地做到了这一点,但是当 bounds_changed 需要超过 100 毫秒的时间来触发时,它看起来很笨拙,并且可能容易出现一些错误。
查看示例:http://jsbin.com/sosurexuke/1/edit?js,console,output
有更好的解决方案吗?
编辑:如果您认为只是检查 map.getBounds() 是否与您发送的 fitBounds() 相同,那么您会失望地知道拟合边界的结果通常甚至不接近你发送的界限。我写了这个函数,认为这可能是可能的
function boundsAreIdentical(bounds1, bounds2)
if (!bounds1 || !bounds2) return false;
var tolerance = 0.00001;
console.log(bounds1.getNorthEast().lat(), bounds2.getNorthEast().lat());
console.log(bounds1.getNorthEast().lng(), bounds2.getNorthEast().lng());
console.log(bounds1.getSouthWest().lat(), bounds2.getSouthWest().lat());
console.log(bounds1.getSouthWest().lng(), bounds2.getSouthWest().lng());
if (
(Math.abs(bounds1.getNorthEast().lat() - bounds2.getNorthEast().lat()) <= tolerance) &&
(Math.abs(bounds1.getNorthEast().lng() - bounds2.getNorthEast().lng()) <= tolerance) &&
(Math.abs(bounds1.getSouthWest().lat() - bounds2.getSouthWest().lat()) <= tolerance) &&
(Math.abs(bounds1.getSouthWest().lng() - bounds2.getSouthWest().lng()) <= tolerance))
return true;
return false;
2 年后编辑:
似乎在谷歌地图 (3.32) 的最新实验版本中,bounds_changed
被触发,即使边界与当前边界相同。
我将原始示例更新为 3.31 版,它仍然显示原始问题。
【问题讨论】:
【参考方案1】:解决这个问题的第一部分(知道边界何时完成更改)的最简单方法是使用idle event listener。
无论您如何更改边界,请在即将更改边界之前设置此事件。这样,当边界全部确定后,地图将注册为空闲并触发空闲事件,您可以在其中进行 shiz。为防止事件相互叠加,请同时清除它。
您可能需要稍微调整一下。说到摆弄,这里有一个小提琴。在这个小提琴中,我只是将警报设置为每次发生:
https://jsbin.com/kapimov/edit?js,output单击“更改边界”,您会看到它一遍又一遍地发生:)
编辑:要检查 fitBounds() 是否在失败时触发,请比较触发 fitBounds() 之前和之后的中心。
即使尝试两次将边界设置为相同的坐标,中心也会发生变化并且可以进行比较。中心检查似乎发生在地图实际移动边界之前,但在调用该函数时总是会发生变化。
点击“Fit Current Bounds”按钮两次以查看它的实际效果;第一次 'bounds_changed' 触发,第二次没有但 center 仍然检查正确。注释掉 fitBounds() 函数,看看没有它中心是如何变化的。
【讨论】:
fitBounds
的调用不能修改地图的边界,这就是这个问题的意义
嗯,我明白了,对于 fitBounds() 无法成功移动地图的情况。我用一个确定的失败案例更新了 Fiddle,使边界与当前边界相同。然后我使用了另一个属性——中心——来检查边界是否总是改变它。事实证明确实如此!编辑了我的答案以反映新的解决方案。
适应当前边界按钮无法正常工作,进入海洋。当我让它工作时,它永远不会触发 bounds_changed。值得注意的是,getCenter 将立即触发,而不是在边界可能发生变化之后触发。也就是说,getCenter 在 fitBounds 后 0.1 毫秒触发,但边界的改变通常发生在 10 毫秒内。为了让中心技巧正常工作,您需要知道 fitBounds 何时完成(您需要回调),这又回到了原来的问题。
边界设置在哪里并不重要;功能是一样的。你指的10ms是动画效果。您是否想知道动画何时结束?不管 fitBounds() 函数是否实际移动了边界,'center_changed' 都会在稍后触发。当 fitBounds() 没有被调用时,'center_changed' 不会触发。对于您正在寻找的情况,这是一个很好的测试 - 当 fitBounds() 被调用但 'bounds_changed' 没有触发时。【参考方案2】:
如问题编辑中所述。如果您可以使用 3.32,那么就使用它。否则,如果您需要一个适用于 3.32 之前的解决方案,那么您可以在拟合边界之前简单地将地图平移 1 个像素。视觉变化不会触发刷新并强制边界始终更改。
演示:http://jsbin.com/bipekaxosa/1/edit?js,console,output
function pan(map, newCenterLatLng, offsetx, offsety, callback)
if (!map.getProjection())
if (callback)
return setTimeout(pan, 1, map, newCenterLatLng, offsetx, offsety, callback);
throw new Error("You must wait until map.getProjection() is ready. Try using the callback instead");
var newCenterLatLngPixels = map.getProjection().fromLatLngToPoint(newCenterLatLng);
var offset = new google.maps.Point(
((typeof (offsetx) == "number" ? offsetx : 0) / Math.pow(2, map.getZoom())) || 0,
((typeof (offsety) == "number" ? offsety : 0) / Math.pow(2, map.getZoom())) || 0
);
map.setCenter(map.getProjection().fromPointToLatLng(new google.maps.Point(
newCenterLatLngPixels.x - offset.x,
newCenterLatLngPixels.y + offset.y
)));
if (callback)
return callback();
function fitBoundsAndCallback(map, bounds, callback)
google.maps.event.addListenerOnce(map, "bounds_changed", function()
if (callback)
callback();
);
// Pan the map 1 pixel up so that bounds will always change
// even in the event you are fitting to the same bounds as before
// Remove this once the move to gmaps 3.32 as bounds_changed works always
this.pan(map, map.getCenter(), 0, 1, function()
map.fitBounds(bounds);
);
【讨论】:
以上是关于谷歌地图 fitBounds 回调的主要内容,如果未能解决你的问题,请参考以下文章