Javascript 扩展GoogleMaps标记以在更新时平滑地设置动画?

Javascript 扩展GoogleMaps标记以在更新时平滑地设置动画?,javascript,google-maps,Javascript,Google Maps,使用GoogleMapsAPIv3,我能够通过AJAX调用更新标记的多个位置。然而,它缺乏任何过渡。代码如下: if ( !latlong.equals( point.latlong ) ) { point.latlong = latlong; point.marker.setPosition(latlong); } 缺点是setPosition没有本机动画方法。是否有人知道扩展设置位置的方法,以便标记器可以流畅地从旧位置“移动”到新位置?或者有什么可用的方法?我没有找到任何文

使用GoogleMapsAPIv3,我能够通过AJAX调用更新标记的多个位置。然而,它缺乏任何过渡。代码如下:

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

缺点是
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]。“transition”函数根据两个动画参数(numDeltas、delay)计算lat和lng的步长。然后它调用“moveMarker”。函数“moveMarker”保留一个简单的计数器,用于指示标记何时到达最终目的地。如果不在那里,它会再次调用自己

下面是一段代码:

希望这有帮助


Bob

如果您想要平滑的动画(带有缓和),这些库应该有助于:


我知道现在很晚了,但这可能会帮助未来的流浪者。
问题陈述:编写一个函数(由于特定的用例而不是库),将google maps标记动画化到新位置。
解决方案基于这个很棒的库

函数animateMarkerTo(标记,新位置){
变量选项={
持续时间:1000,
放松:函数(x,t,b,c,d){//jquery动画:swing(easeOutQuad)
返回-c*(t/=d)*(t-2)+b;
}
};
window.requestAnimationFrame=window.requestAnimationFrame | | window.mozRequestAnimationFrame | | window.webkitRequestAnimationFrame | | window.msRequestAnimationFrame;
window.cancelAnimationFrame=window.cancelAnimationFrame | | window.mozCancelAnimationFrame;
//保存当前位置。加前缀以避免名称冲突。将lat/lng分开以避免在每个帧中调用lat()/lng()
marker.AT_startPosition_lat=marker.getPosition().lat();
marker.AT_startPosition_lng=marker.getPosition().lng();
var newPosition_lat=newPosition.lat();
var newPosition_lng=newPosition.lng();
//穿越180°子午线,绕地球走很长一段路?
if(数学绝对值(新位置lng-标记器在起始位置lng)>180){
if(新位置lng>开始位置处的标记){
新位置_lng-=360;
}否则{
新位置_lng+=360;
}
}
var animateStep=函数(标记,开始时间){
var ellapsedTime=(新日期()).getTime()-startTime;
var durationRatio=ellapsedTime/options.duration;//0-1
var easingDurationRatio=期权.宽松(durationRatio,ellapsedTime,0,1,期权.期限);
if(持续时间比率<1){
标记设置位置({
拉丁美洲:(
开始位置处的标记+
(新位置-起始位置标记)*测量持续时间比率
),
液化天然气:(
标记。在开始位置+
(新位置液化天然气-标记在起始位置液化天然气)*测量持续时间比率
)
});
//如果此浏览器上存在requestAnimationFrame,请使用它。如果不存在,请使用每秒60帧的setTimeout
if(window.requestAnimationFrame){
marker.AT_animationHandler=window.requestAnimationFrame(函数(){animateStep(marker,startTime)});
}否则{
marker.AT_animationHandler=setTimeout(函数(){animateStep(marker,startTime)},17);
}
}否则{
标记器。设置位置(新位置);
}
}
//停止运行动画
if(window.cancelAnimationFrame){
window.cancelAnimationFrame(marker.AT_animationHandler);
}否则{
clearTimeout(marker.AT_animationHandler);
}
animateStep(marker,(newdate()).getTime());
}

很好的解决方案!我修改了你的代码,以便能够添加一个以公里/小时为单位的特定速度:@pmrotule Great one。我试图修改以在标记上显示动态标签。但可能是因为它不断地改变标记,它没有显示出来。知道我该怎么做吗?@User-8017771不知道,我得看看你的代码。我猜当你改变位置时,它会隐藏标签。要完全控制标记的外观,可以使用@pmrotule之类的东西,我没有对代码做太多更改。。为了测试,我在js小提琴中添加了标签作为纬度。第72行和第73行:
label:startPos[0],title:startPos[0]
可能还需要做其他事情吗?@User-8017771我不明白为什么要将标签设置为纬度
label
google.maps.Marker
的一个选项,因此您可以在创建标记时对其进行设置,或者稍后使用
.setOptions()
对其进行更新。例如,在我的小提琴中,可以添加
marker.setOptions({label:lat.toString()})在函数的末尾
moveMarker()
。如果您需要更多帮助,请在Stackoverflow上创建一个新问题。谢谢。它实际上可以工作,但在我的实现中,它留下了幽灵标记。我该如何解决这个问题?你能提供更多的信息吗?或者一把小提琴?谢谢你的快速回复。我在一个角度应用程序中使用这个函数,其中坐标来自Firebase。问题是,在最初的几次移动之后,标记的图标会扭曲和收缩。记号笔移动平稳
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());
}