анимация javascript: почему следующая строка запускается до того, как анимация завершена? - PullRequest
0 голосов
/ 06 октября 2011

У меня возникают проблемы, когда я пытаюсь оживить элемент. У меня есть рекурсивная функция 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 ]

2 голосов
/ 06 октября 2011

Это не работает, потому что JS, в частности setTimeout, является асинхронным, то есть не блокируется (сон / ожидание / и т. Д.). Вы в основном устанавливаете время ожидания, а затем продолжаете работу с остальной частью кода. JS вызывает вашу функцию по истечении времени и больше ничего не делает.

Большую часть времени вы можете обойти это, передав обратный вызов, который вы вызываете, когда анимация завершается (вместо или одновременно с установкой done, это будет простой способ).

0 голосов
/ 06 октября 2011

Короче говоря, 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); });
0 голосов
/ 06 октября 2011

Попробуйте следующий немного измененный код:

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...