如何在Javascript中按顺序执行多个动画,每个动画都有延迟

时间:2016-12-06 07:10:12

标签: javascript animation canvas

我试图为河内塔问题制作动画。我目前的动画格式依赖于单独移动每个木制件。一件作品的每个动作都需要一个动画。我解决问题的函数调用函数,然后移动相应的部分。

function hanoi(n, source, destination, buffer){
if (n == 1){
    var newBlock = source.stack.pop()

    destination.stack.push(newBlock);
    moveBlock(newBlock, destination.x - source.x + newBlock.x, 500 - 62 * (1 + destination.stack.length));
} else {
    hanoi(n-1, source, buffer, destination);

    var newBlock = source.stack.pop()
    destination.stack.push(newBlock);
    moveBlock(newBlock, destination.x - source.x + newBlock.x, 500 - 62 * (1 + destination.stack.length));

    hanoi(n-1, buffer, destination, source);
}
}

moveBlock函数相当笨拙,因为我在向动画本身添加延迟时遇到了问题。对于运动动画的三个片段,它调用不同的功能。我这样做是因为我无法理解如何有效地延迟Javascript的延迟。

function moveBlock(block, x2, y2){
    var id = setInterval(moveUp, speed);
    function moveUp() {
        if (block.y <= 50){
            draw();
            clearInterval(id);
            moveBlockOver(block, x2, y2);
        } else {
            block.y = block.y - 5;
            draw();
        }
    }
}
function moveBlockOver(block, x2, y2){
    var negative = -(block.x - x2)/(Math.abs(block.x - x2));
    var id = setInterval(moveOver, speed);
    function moveOver() {
        if (block.x == x2){
            draw();
            clearInterval(id);
            moveBlockDown(block, x2, y2);
        } else {
            block.x = block.x + 5 * negative;
            draw();
        }
    }
}
function moveBlockDown(block, x2, y2){
    var id = setInterval(moveDown, speed);
    function moveDown() {
        if (block.y >= y2){
            draw();
            go = true;
            clearInterval(id);
        } else {
            block.y = block.y + 5; 
            draw();
        }
    }
}

我怎样才能更好地格式化代码来解决这个问题?如果我可以在javascript代码中延迟,但显然这是不可能的,这会简单得多。

1 个答案:

答案 0 :(得分:0)

请勿使用setTimeoutsetInterval使用requestAnimationFrame

var playing = true;
function update(timer) { // Main update loop
    // your draw code

    if(playing){
        requestAnimationFrame(update); // get next frame
    }
}
requestAnimationFrame(update); // starts the animation

要制作动画,请为完成后返回true的每个动画创建一些函数

function anim1(){
    drawFoo(); // draw function
    foo.x += 5;
    return foo.x > 100; // returns true when foo.x > 100
}

function anim2(){
    drawFoo(); // draw function
    foo.y += 5;
    return foo.y > 100; // returns true when foo.y > 100
}

function anim3(){
    drawFoo(); // draw function
    foo.x -= 5;
    return foo.x < 0; // returns true when foo.x < 0
}

然后创建一个包含动画功能的堆栈,以便运行它们,并使用var来保存当前动画

 // repeat 2 times
var animStack = [anim1,anim2,anim3,anim1,anim2,anim3];
var currentAnim; 

然后在update循环

 if(currentAnim === undefined){ // is there an animation 
     // no animation 
     if(animStack.length > 0){  // are there any animations on the stack
         currentAnim = animStack.shift(); // yes get the first anim
     }else{
         playing = false;  // no animations to play so stop and exit
         return;
     }
 }
 if(currentAnim()){ // call the anim and check if returns true;
     // animation ended so get the next animation function if there are any
     if(animStack.length > 0){
         currentAnim = animStack.shift(); // get the next anim
     }else{
         playing = false; // no more animations so stop
         currentAnim = undefined; // ready for new animtion
     }
 }         

动画功能将一个接一个地播放直到完成。要添加新动画,只需将它们推到动画堆栈并调用startAnimation函数

即可
function startAnimation(){  // function restarts the anim safely
    if(!playing){  // has the animation stopped
        playing = true;   // yes then restart
        requestAnimationFrame(update)`
    }
    // if the animation is playing then no need to restart
}