javascript动画:为什么下一行在动画完成之前运行?

时间:2011-10-06 05:26:21

标签: javascript animation

我遇到的问题是我试图为元素设置动画。我有一个递归函数animate,包含setTimeout来延迟动画。问题是调用递归方法之后的下一行在调用动画之前运行。例如,使用此代码:

this.slideTo = function(x,y) {
    var originalStyle = this.element.style.cssText;

    var endX = x;
    var endY = y;
    var pos = this.getPosition();
    var startX = pos.x;
    var startY = pos.y; 
    var distX = x - pos.x;
    var distY = y - pos.y;
    var totalDistance = Math.sqrt((distX*distX) + (distY*distY));
    var count = 0;
    var done = false;

    animate(this.element);
    function animate(element) {         
        count += 5;
        var curPos = _(element).getPosition();
        var curDistX =  endX - curPos.x;
        var curDistY = endY - curPos.y;
        var curDistance = Math.sqrt((curDistX*curDistX) + (curDistY*curDistY));
        var percentDone = count/totalDistance;
        var moveToX = Math.round((percentDone*distX) + startX);
        var moveToY = Math.round((percentDone*distY) + startY);
        _(element).moveTo(moveToX,moveToY);
        if(percentDone <= 1) {
            setTimeout(function(){animate(element);},1);
        } else {
            done = true;
        }
    }
    console.log(done);

    this.element.style.cssText = originalStyle;
}

控制台显示false,因为它在动画完成之前运行。我怎么解决这个问题?顺便说一句:这是在鼠标事件上调用的。这与它有什么关系吗?

3 个答案:

答案 0 :(得分:2)

它不起作用,因为JS,特别是setTimeout是异步的 - 也就是说,它不会阻塞(睡眠/等待/等)。您基本上是设置超时,然后继续使用其余代码。当时间结束时,JS会调用你的函数,而它没有做任何事情。

大多数情况下,您可以通过传入动画完成时调用的回调来解决此问题(而不是设置done或同时设置{{1}},这将是直截了当的方式。)

答案 1 :(得分:0)

尝试下一个小改变的代码:

this.slideTo = function(x,y) {
    var originalStyle = this.element.style.cssText;

    var endX = x;
    var endY = y;
    var pos = this.getPosition();
    var startX = pos.x;
    var startY = pos.y; 
    var distX = x - pos.x;
    var distY = y - pos.y;
    var totalDistance = Math.sqrt((distX*distX) + (distY*distY));
    var count = 0;
    var done = false;

    function restoreState(element) {
        element.style.cssText = originalStyle;
        /// ....
    }

    function animate(element) {         
        count += 5;
        var curPos = _(element).getPosition();
        var curDistX =  endX - curPos.x;
        var curDistY = endY - curPos.y;
        var curDistance = Math.sqrt((curDistX*curDistX) + (curDistY*curDistY));
        var percentDone = count/totalDistance;
        var moveToX = Math.round((percentDone*distX) + startX);
        var moveToY = Math.round((percentDone*distY) + startY);
        _(element).moveTo(moveToX,moveToY);
        if(percentDone <= 1) {
            setTimeout(function(){animate(element);},1);
        } else {
            done = true;
            restoreState(element);
        }
    }

    animate(this.element);
}

答案 2 :(得分:0)

简而言之,setTimeout不会停止代码的执行 - 它只是在给定的超时后运行有问题的函数:

var a = 'now';
function go(){ a = 'later'; };
setTimeout(go, 50);
console.log(a); // 'now'
setTimeout(function(){ console.log(a); },51); // 'later'

您想使用回调模式:

function animate(element, callback){
  // do some stuff
  if(stuffDone){
    callback();
  }
}
animate(element, function(){console.log(whatever); });