Mam problemy, w których próbuję animować elementu. Mam animowany rekurencyjną funkcję, która zawiera ustalanie, aby opóźnić animację. Problem polega na tym, że następny wiersz po wywołaniu metody rekurencyjnej zostaje uruchomione przed nazwą animacji. Na przykład z tym kodem:

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

Konsola wyświetla false, ponieważ jest uruchomiony przed zakończeniem animacji. Jak mogę to rozwiązać? BTW: Jest to wywołane na imprezie myszy. Czy to może z tym zrobić coś wspólnego?

0
justspamjustin 6 październik 2011, 09:26

3 odpowiedzi

Najlepsza odpowiedź

Spróbuj następny mały zmieniony kod:

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);
}
0
Andrew D. 6 październik 2011, 05:36

Nie działa, ponieważ JS, a zwłaszcza {X0}}, jest asynchroniczne - to znaczy, nie blokuje (snu / wait / etc). Zasadniczo ustawiasz limit czasu, a następnie kontynuujesz z resztą kodu. JS nazywa twoją funkcję, gdy upłynął czas i nie robi nic innego.

Przez większość czasu możesz pracować wokół tego, przechodząc w wywołanie wywołania, gdy animacja kończy się (zamiast lub w tym samym czasie, co ustawienie done byłby prosty sposób).

2
cHao 6 październik 2011, 05:36

Krótko mówiąc, Settimeout nie zatrzymuje wykonywania kodu - po prostu działa w pytaniu po danym limicie czasu:

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

Chcesz użyć wzoru wywołania zwrotnego:

function animate(element, callback){
  // do some stuff
  if(stuffDone){
    callback();
  }
}
animate(element, function(){console.log(whatever); });
0
Daniel Mendel 6 październik 2011, 05:37