扩展谷歌地图标记动画顺利更新

Extend Google Maps marker to animate smoothly on update?

本文关键字:更新 动画 谷歌 地图 图标 扩展      更新时间:2023-09-26

使用Google Maps API v3,我已经能够通过AJAX调用更新标记的多个位置。然而,它缺乏任何过渡。下列代码:

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

缺点是setPosition没有原生动画方法。有人知道有什么方法可以扩展setPosition,使标记可以流畅地从旧位置"移动"到新位置吗?或者其他可用的方法?我没能找到任何文件。谢谢!

我没有找到任何本地的方法来创建这个动画。您可以通过使用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);
    }
}

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

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

希望对你有帮助。

鲍勃

如果你想要平滑的动画(带有缓动),这些库应该会有所帮助:

https://github.com/terikon/marker-animate-unobtrusive

http://terikon.github.io/marker-animate-unobtrusive/demo/unobtrusive/markermove-sliding.html

我知道有点晚了,但它可能会帮助未来的SO流浪者。
问题说明:写一个函数(而不是一个库,由于特定的用例)动画一个谷歌地图标记到一个新的位置。
解决方案基于这个很棒的库标记-动画-不引人注目

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());
}