我试图为河内塔问题制作动画。我目前的动画格式依赖于单独移动每个木制件。一件作品的每个动作都需要一个动画。我解决问题的函数调用函数,然后移动相应的部分。
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代码中延迟,但显然这是不可能的,这会简单得多。
答案 0 :(得分:0)
请勿使用setTimeout
或setInterval
使用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
}