2011-10-06 10 views
0

요소를 애니메이션화 할 때 문제가 발생합니다. 애니메이션을 지연시키기 위해 setTimeout을 포함하는 재귀 함수 animate가 있습니다. 문제는 재귀 메서드가 호출 된 후 다음 줄이 애니메이션이 호출되기 전에 실행된다는 것입니다. 예 :이 코드의 경우 :자바 스크립트 애니메이션 : 왜 애니메이션이 끝나기 전에 다음 줄이 실행됩니까?

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를 표시합니다. 이 문제를 어떻게 해결할 수 있습니까? btw : 이것은 마우스 이벤트에서 호출됩니다. 그게 그 일과 관련이 있을까요?

+0

* setTimeout *이 비동기 적으로 실행되기 때문에 다음 코드 행은 immediatel y, * setTimeout *에 대한 일시 중지가 없습니다. 함수가 완료된 후에 실행됩니다. – RobG

답변

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

JS, 특히 setTimeout은 비동기 적입니다. 즉, 차단되지 않습니다 (절전/대기/등). 기본적으로 제한 시간을 설정 한 다음 나머지 코드와 함께 계속 진행합니다. JS는 시간이 경과하고 다른 일을하지 않을 때 함수를 호출합니다.

대개의 경우 애니메이션이 완료 될 때 (예 : done 설정과 동시에 또는 동시에 설정하는 것이 간단한 방법 일 수 있음) 호출 할 때 콜백을 전달하여이 문제를 해결할 수 있습니다.

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); }); 
관련 문제