如何在Javascript中制作动画一次?

时间:2017-10-06 02:34:29

标签: javascript html css html5 html5-canvas

我已经看了好几个小时,但我无法弄清楚如何满足我的需求。

我试图制作它,以便在触发后在特定的X和Y位置播放动画。 (例如,在坦克被摧毁后播放爆炸动画)

我有这样的功能:

var explosion = new Image();
explosion.src = "https://i.imgur.com/gWjqlKe.png";

function animate(img, x, y, width, height, steps){
  steps = Math.floor(steps);
  context.clearRect(x, y, width, height);
  context.drawImage(img, width * step, 0, width, height);
  step += .3;
  requestAnimationFrame(animate(img, x, y, width, height, steps));
}

然后当我需要打电话时,我做了:

animate(explosions, tank.x, tank.y, 100, 100, 10);

但是当我摧毁坦克时没有任何反应。

我的代码基于本教程:https://www.youtube.com/watch?v=yna816VY8rg

任何帮助将不胜感激!非常感谢!

编辑:

我现在正在尝试使用setInterval,但它仍然没有用...

var explosion = new Image();
explosion.src = "https://i.imgur.com/gWjqlKe.png";


// Animation Functions

function animate(img, x, y, width, height, endframe){
  var frame = 0;
  frame = setInterval(animation(frame, img, x, y, width, height), 1000);
  if (frame >= endframe){
    clearInterval(frame)
  }

}

function animation(frame, img, x, y, width, height){
  ctx = gameArea.context;
  ctx.drawImage(img, x * frame, y, width, height);
  frame ++;
  return frame;

编辑2:

我从我的Reddit中意识到我在requestAnimationFrame和setInterval中犯了一个错误,所以我再次编辑但它仍然不起作用:

function animate(img, x, y, width, height, endframe){
  var frame = 0;
  frame = setInterval(function() {
    animation(frame, img, x, y, width, height);
  }, 1000);
  if (frame >= endframe){
    clearInterval(frame)
  }

}

function animation(frame, img, x, y, width, height){
  ctx = gameArea.context;
  ctx.drawImage(img, x * frame, y, width, height);
  frame ++;
  return frame;

}

function animate(img, x, y, width, height, steps){
  steps = Math.floor(steps);
  context.clearRect(x, y, width, height);
  context.drawImage(img, width * step, 0, width, height);
  step += .3;
  requestAnimationFrame(animate(img, x, y, width, height, steps));
}

1 个答案:

答案 0 :(得分:1)

一个主要循环来统治它们。

使用事件计时器通过requestAnimationFrame启动动画循环将导致各种问题。 requestAnimationFrame将以与最后一帧相同的顺序触发下一帧。如果超时在任何其他帧之前的帧中进入,它将是第一个绘制到画布的函数,那么其他帧将绘制在顶部。

评论中指出的nnnnnnn仅使用一个游戏循环,为了让渲染顺序正确,可以节省很多不必要的复杂性。

requestAnimationFrame时间参数

requestAnimationFrame提供了一个计时器作为第一个参数。此计时器是当前帧时间,而不是实际时间。这使您可以从V sync(显示刷新)计算时间

计时和动画示例

在设定的时间内为某些FX设置动画,记录开始时间,设置持续时间并为frame参数中给出的时间设置动画。

该示例显示了主循环中使用的简单爆炸计时器。您需要提供当前帧时间时开始计时器。当它处于活动状态时,你给它当前时间,它会更新自己的相对时间,完成后active标志设置为false。您可以通过current时间从0到长度

渲染动画

这只是一个动画,你可以使用一堆这样的时间对象,为每个定时动画添加到堆栈中。

const explode = {
   start : null,
   length : 1000,
   current : 0,
   active : false,
   begin(time,length = this.length){
       this.start = time;
       this.length = length;
       this.active = true;
       this.current = 0;
   },
   getCurrent(time){
       this.current = time - this.start;
       this.active =  this.current <= this.length;
       return this.current;
   }
}

var tankDead = false;     
function mainLoop(time){ // time is supplied by requestAnimationFrame
   if(tankDead ) {   
      tankDead = false;
      explode.begin(time,2000); // two seconds
   }

   if(explode.active){
       explode.getCurrent(time);
       if(explode.active){
           // explode.current is the time
           // draw the animation at time explode.current
       } else {
           // explosion is complete
       }


   }
   requestAnimationFrame(mainLoop);
}      
requestAnimationFrame(mainLoop);

通过勾选时间动画。

虽然我更喜欢固定帧率方法,但只是倒计时定时器

var tankDead = false;     
var explodeTick = 0;
function mainLoop(time){ // time is supplied by requestAnimationFrame
   if(tankDead ) {   
      tankDead = false;
      explodeTick = 60 * 2; // two seconds
   }

   if(explodeTick > 0){
       explodeTick -= 1;
       // draw the animation at time explosion
   }
   requestAnimationFrame(mainLoop);
}      
requestAnimationFrame(mainLoop);

管理起来要简单得多,没有人会注意到你放弃了一两帧,而且只需要花费不到一秒的时间。