Javascript 扩展 Google 地图标记以在更新时平滑动画?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5892113/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 19:23:30  来源:igfitidea点击:

Extend Google Maps marker to animate smoothly on update?

javascriptgoogle-maps

提问by crockpotveggies

Using the Google Maps API v3 I've been able to update multiple positions of markers via an AJAX call. However, it lacks any transition. Code below:

使用 Google Maps API v3,我已经能够通过 AJAX 调用更新标记的多个位置。但是,它没有任何过渡。代码如下:

if ( !latlong.equals( point.latlong ) ) {
    point.latlong = latlong;
    point.marker.setPosition(latlong);
}

The drawback is that setPositionhas no native animation method. Does anyone know any methods for extending setPositionso the marker can fluently "move" from it's old to new position? Or any methods available? I have not been able to find any documentation. Thanks!

缺点是setPosition没有原生动画方法。有谁知道任何扩展方法,setPosition以便标记可以流畅地从旧位置“移动”到新位置?或者有什么可用的方法?我找不到任何文档。谢谢!

回答by rcravens

I did not find any native way to create this animation. You can create your own animation by stepping the position from the current point to the final point using the setPosition. Here is a code snippet to give you an idea:

我没有找到任何本地方式来创建这个动画。您可以通过使用 setPosition 将位置从当前点步进到最终点来创建自己的动画。这是一个代码片段,可以给您一个想法:

var map = undefined;
var marker = undefined;
var position = [43, -89];

function initialize() {

    var latlng = new google.maps.LatLng(position[0], position[1]);
    var myOptions = {
        zoom: 8,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

    marker = new google.maps.Marker({
        position: latlng,
        map: map,
        title: "Your current location!"
    });

    google.maps.event.addListener(map, 'click', function(me) {
        var result = [me.latLng.lat(), me.latLng.lng()];
        transition(result);
    });
}

var numDeltas = 100;
var delay = 10; //milliseconds
var i = 0;
var deltaLat;
var deltaLng;
function transition(result){
    i = 0;
    deltaLat = (result[0] - position[0])/numDeltas;
    deltaLng = (result[1] - position[1])/numDeltas;
    moveMarker();
}

function moveMarker(){
    position[0] += deltaLat;
    position[1] += deltaLng;
    var latlng = new google.maps.LatLng(position[0], position[1]);
    marker.setPosition(latlng);
    if(i!=numDeltas){
        i++;
        setTimeout(moveMarker, delay);
    }
}

This can probably be cleaned up a bit, but will give you a good start. I am using JavaScript's setTimeout method to create the animation. The initial call to 'transition' gets the animation started. The parameter to 'transition' is a two element array [lat, lng]. The 'transition' function calculates the step sizes for lat and lng based upon a couple of animation parametes (numDeltas, delay). It then calls 'moveMarker'. The function 'moveMarker' keeps a simple counter to indicate when the marker has reached the final destination. If not there, it calls itself again.

这可能会稍微清理一下,但会给你一个良好的开端。我正在使用 JavaScript 的 setTimeout 方法来创建动画。对 'transition' 的初始调用使动画开始。'transition' 的参数是一个两元素数组 [lat, lng]。'transition' 函数根据几个动画参数(numDeltas、delay)计算 lat 和 lng 的步长。然后它调用'moveMarker'。函数“moveMarker”保持一个简单的计数器来指示标记何时到达最终目的地。如果不存在,它会再次调用自己。

Here is a jsFiddle of the code working: https://jsfiddle.net/rcravens/RFHKd/2363/

这是代码工作的jsFiddle:https://jsfiddle.net/rcravens/RFHKd/2363/

Hope this helps.

希望这可以帮助。

Bob

鲍勃

回答by mohitSehgal

I know its late but it might help the future SO wanderers.
Problem Statement:write a function(and not a library due to specific use-case) to animate a google maps marker to a new location.
Solutionis based on this awesome library marker-animate-unobtrusive

我知道为时已晚,但它可能会对未来的 SO 流浪者有所帮助。
问题陈述:编写一个函数(由于特定用例而不是库)来将谷歌地图标记动画化到新位置。
解决方案基于这个很棒的库mark-animate-unobtrusive

function animateMarkerTo(marker, newPosition) {
    var options = {
        duration: 1000,
        easing: function (x, t, b, c, d) { // jquery animation: swing (easeOutQuad)
            return -c *(t/=d)*(t-2) + b;
        }
    };

    window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
    window.cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame;

    // save current position. prefixed to avoid name collisions. separate for lat/lng to avoid calling lat()/lng() in every frame
    marker.AT_startPosition_lat = marker.getPosition().lat();
    marker.AT_startPosition_lng = marker.getPosition().lng();
    var newPosition_lat = newPosition.lat();
    var newPosition_lng = newPosition.lng();

    // crossing the 180° meridian and going the long way around the earth?
    if (Math.abs(newPosition_lng - marker.AT_startPosition_lng) > 180) {
        if (newPosition_lng > marker.AT_startPosition_lng) {
            newPosition_lng -= 360;
        } else {
            newPosition_lng += 360;
        }
    }

    var animateStep = function(marker, startTime) {
        var ellapsedTime = (new Date()).getTime() - startTime;
        var durationRatio = ellapsedTime / options.duration; // 0 - 1
        var easingDurationRatio = options.easing(durationRatio, ellapsedTime, 0, 1, options.duration);

        if (durationRatio < 1) {
            marker.setPosition({
                lat: (
                    marker.AT_startPosition_lat +
                    (newPosition_lat - marker.AT_startPosition_lat)*easingDurationRatio
                ),
                lng: (
                    marker.AT_startPosition_lng +
                    (newPosition_lng - marker.AT_startPosition_lng)*easingDurationRatio
                )
            });

            // use requestAnimationFrame if it exists on this browser. If not, use setTimeout with ~60 fps
            if (window.requestAnimationFrame) {
                marker.AT_animationHandler = window.requestAnimationFrame(function() {animateStep(marker, startTime)});
            } else {
                marker.AT_animationHandler = setTimeout(function() {animateStep(marker, startTime)}, 17);
            }

        } else {
            marker.setPosition(newPosition);
        }
    }

    // stop possibly running animation
    if (window.cancelAnimationFrame) {
        window.cancelAnimationFrame(marker.AT_animationHandler);
    } else {
        clearTimeout(marker.AT_animationHandler);
    }

    animateStep(marker, (new Date()).getTime());
}