我希望能够在谷歌地图上平滑地放大标记。如果仅在双击时设置缩放比例,地图会突然处于该缩放级别,没有任何平稳过渡。
只有比当前级别多放大一个级别时,谷歌地图才显示出漂亮的平滑过渡。因此,应该可以平滑地放大超过一个级别,但是如何做到呢?
只有比当前级别多放大一个级别时,谷歌地图才显示出漂亮的平滑过渡。因此,应该可以平滑地放大超过一个级别,但是如何做到呢?
碰巧最近我也想实现同样的效果,并找到了一个解决方案,我写了一篇文章介绍。基本上,只为每个过渡设置延时不够,因为如果Google的缩放效果还没有完成或者已经完成很久,它很容易导致“开始-停止”类型的缩放。
正如Martin提到的,这种方法有一些缺点,我就不再赘述了。最终是否使用此方法取决于您的选择,主要取决于用户的CPU性能和/或浏览器。但是,当明智使用时,这确实是一个不错的效果,可以给人留下深刻印象。
我的解决方案如下:
// example marker:
var marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(-20.3,30.3)
});
// add the double-click event listener
google.maps.event.addListener(marker, 'dblclick', function(event){
map = marker.getMap();
map.setCenter(overlay.getPosition()); // set map center to marker position
smoothZoom(map, 12, map.getZoom()); // call smoothZoom, parameters map, final zoomLevel, and starting zoom level
});
// the smooth zoom function
function smoothZoom (map, max, cnt) {
if (cnt >= max) {
return;
}
else {
z = google.maps.event.addListener(map, 'zoom_changed', function(event){
google.maps.event.removeListener(z);
smoothZoom(map, max, cnt + 1);
});
setTimeout(function(){map.setZoom(cnt)}, 80); // 80ms is what I found to work well on my system -- it might not work well on all systems
}
}
基本上来说,这个问题是通过每次将缩放级别调整一个单位并监听zoom_changed
事件,等待80毫秒后再次将缩放级别调整一个单位等方式解决的。这样做的好处在于zoom_changed
事件似乎在谷歌地图提供的平滑过渡后被调用,但在实际图像加载之前,因此不会浪费太多带宽。这个对我非常有效:
function animateMapZoomTo(map, targetZoom) {
var currentZoom = arguments[2] || map.getZoom();
if (currentZoom != targetZoom) {
google.maps.event.addListenerOnce(map, 'zoom_changed', function (event) {
animateMapZoomTo(map, targetZoom, currentZoom + (targetZoom > currentZoom ? 1 : -1));
});
setTimeout(function(){ map.setZoom(currentZoom) }, 80);
}
}
终于有一篇来自谷歌的示例,教你如何实现它。
对于一个简单的js
实现,你需要包含tween.js并使用以下代码:
/* Setup */
const cameraOptions = {
center: { lat: /* latitude value */, lng: /* longitude value */ },
zoom: /* zoom value */
};
const mapOptions = Object.assign(Object.assign({}, cameraOptions));
let map = new google.maps.Map(document.getElementById("map"),
mapOptions
);
/* Animation */
new TWEEN.Tween(cameraOptions)
.to({ zoom: /* new zoom value */ }, 1000)
.easing(TWEEN.Easing.Quadratic.InOut) /* https://sole.github.io/tween.js/examples/03_graphs.html */
.onUpdate(() => {
map.moveCamera(cameraOptions);
})
.start();
// Setup the animation loop.
function animate(time) {
requestAnimationFrame(animate);
TWEEN.update(time);
}
requestAnimationFrame(animate);
您还可以同时动画化缩放
和中心点
,例如通过声明新的中心点:
.to({ zoom: /* new zoom value */, center: { lat: /* new latitude value */, lng: /* new longitude value */ } }, 1000)
function smoothZoom(map, level, cnt, mode)
{
if(mode == true)
{
if (cnt >= level) {
return;
}
else
{
if((maxZoomOut + 2) <= cnt)
{
var z = google.maps.event.addListener(map, 'zoom_changed', function(event)
{
google.maps.event.removeListener(z);
map.setCenter(marker.getPosition());
smoothZoom(map, level, cnt + 1, true);
});
setTimeout(function(){map.setZoom(cnt);}, timeOut);
}
else
{
map.setZoom(cnt);
smoothZoom(map, level, cnt + 1, true);
}
}
}
else
{
if (cnt < level) {
return;
}
else
{
var z = google.maps.event.addListener(map, 'zoom_changed', function(event)
{
google.maps.event.removeListener(z);
map.setCenter(marker.getPosition());
smoothZoom(map, level, cnt - 1, false);
});
if(maxZoomIn - 2 <= cnt)
{
map.setZoom(cnt);
}
else
{
setTimeout(function(){map.setZoom(cnt);}, timeOut);
}
}
}
}
我已经创建了一些变量,比如timeOut和maxZoomInOut...你可以在jsfiddle上找到完整的代码http://jsfiddle.net/dexy86/9afy9/
我尝试了上面提供的替代方法,但是每当我在桌面浏览器或移动应用程序中查看转换时,它都会立即发生,或者至少在每个循环迭代之间的时间内不可感知,至少在我试用的硬件上是如此。
我使用了与其他方法相同的循环,但更改了超时时间,以便在缩放级别较高时缩放更快,在较低时缩放更慢,因此结果更加明显。
我没有使用固定的超时时间,而是将第一个超时时间设置为0,然后将后续超时时间设置为以下快速且简单的方程式。
((1+ currentZoom) / maxZoom) * 500;
timeout = (1+map.getZoom() / 18) * 500;
这将平滑地缩放到所需位置。尝试添加以下行:
LatLng latLng = new LatLng(lat,lng);
map.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, ZOOM_FACTOR));
self.
删除以避免混淆。 - Fagner BrackaddListenerOnce
жқҘйҒҝе…ҚеҲ йҷӨзӣ‘еҗ¬еҷЁзҡ„ж“ҚдҪңгҖӮ - Chris