如何在Google地图中的标记上平滑放大?

Pea*_*lly 40 javascript google-maps

我希望能够在Google地图中的标记上平滑放大.如果只是双击设置缩放,则地图突然在该缩放级别上,没有任何平滑过渡.

缩放比当前级别更进一步,谷歌地图显示了一个很好的平滑过渡.因此,必须可以平滑放大多个级别,但如何?

Her*_*aaf 60

幸运的是,我想最近达到同样的效果,并找到了一个解决方案,我发了一篇文章.基本上,仅为每次转换设置超时是不够的,因为如果谷歌的缩放效果尚未完成,或者已经很久完成,它可能很容易导致"开始 - 停止"类型的缩放.

正如马丁所说,这有一些缺点,我不会重申.您最终是否使用它是您的选择,并且在很大程度上取决于您的用户的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
    }
}  
Run Code Online (Sandbox Code Playgroud)

基本上它归结为将缩放级别调整为1,监听zoom_changed事件,等待80ms然后再将缩放级别调整为1,等等.这样做的好处是zoom_changed事件似乎在提供平滑过渡后调用通过谷歌地图,但加载实际图像之前,所以它不会浪费太多带宽.

超时中的80ms也是我提出的一个神奇的数字 - 建议你做一个更彻底的测试,看看哪些在不同的系统和浏览器上有效,并且可能根据你的发现略有改变算法或不同系统.

每次都可能没有必要添加和删除监听器,但如果您愿意,可以自己进行小改进.

  • 奇迹般有效!而不是setCenter,如果你使用panTo它看起来更好......;) (5认同)
  • 这种肮脏的方法尽可能接近,不幸的是,它不可靠.网络延迟可以让它看起来很傻.还是,不错的尝试:/ (4认同)
  • 您可以使用`addListenerOnce`来保存删除侦听器 (2认同)

Igo*_*hin 10

这个很适合我:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)


LS_*_*LS_ 5

谷歌终于有一个关于如何做到这一点的例子。对于简单的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);
Run Code Online (Sandbox Code Playgroud)

例如,您还可以通过声明新中心来同时为zoom两者设置动画:center

.to({ zoom: /* new zoom value */, center: { lat: /* new latitude value */, lng: /* new longitude value */ } }, 1000)
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你 - **注意** 我损失了一个小时,只是因为 Google 文档页面链接到了错误的 Tween 库(非常相似)!正确的 Tween 库是此答案中链接的库。 (2认同)