如何调整动画的速度

How do I adjust the speed of an animation?

本文关键字:动画 速度 调整 何调整      更新时间:2023-09-26

我想创建一个弹跳球,我可以调整它反弹的速度

这是我的原始代码

 <script>
      var context;
      var x=100;
      var y=200;
      var dx=5;
      var dy=5;

      function init()
      {
         context= myCanvas.getContext('2d');
         setInterval(draw,100);
      }

      function draw()
      {
        context.clearRect(0,0, 300,300);
        context.beginPath();
        context.fillStyle="#B76EB8";
        // Draws a circle of radius 20 at the coordinates 100,100 on the canvas
        context.arc(x,y,20,0,Math.PI*2,true);
        context.closePath();
        context.fill();
        if( (x-20)<0 || (x+20)>300) dx=-dx; 
        if( (y-20)<0 || (y+20)>300) dy=-dy; 
        x+=dx; 
        y+=dy;
  }
</script>

然而,当我通过setInterval 降低球速时,我发现动画滞后

所以我用了

  function init()
  {
    context= myCanvas.getContext('2d');
    (function animloop(){
      requestAnimFrame(animloop);
      draw();
      setTimeout(animLoop, 1);
    })();
  }

使动画更平滑

但现在我根本无法调整弹跳球的速度,还有其他建议我可以实现目标的方法吗?

感谢

超时/间隔应不小于20ms,动画功能应根据经过的增量时间设置动画。这将产生一致的动画(离散位置函数可能更好,但简单的增量时间方法通常足够好)。

然后,可以控制(并且独立于)任何间隔量的总球速。记住公式:d = d0 + v * t。原始代码缺少tdelta time)组件,x+=dx实际上等效于x = x0 + dx * 1。然而,间隔之间的时间不必是恒定的,应该用一点数学来补偿。

考虑一下这个演示:

var interval=20;
var x=100;
var y=200;
var dx=100/1000; // px/1000millis
var dy=100/1000;
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var w=canvas.getAttribute("width") || 0;
var h=canvas.getAttribute("height") || 0;
var prevTime = +(new Date)
function draw()
{
    var now = +(new Date)
    var delta = now - prevTime;
    if (delta < 5) {
       // Timeout occured too fast, we could be "stacking"
       // setInterval events, abort!
       return;
    }
    prevTime = now;
    // We now have "delta time millis" to get work done
    // Do movement before draw
    // (This bound check can actually get the
    //  ball stuck, but that's a different question!)
    if( (x-20)<0 || (x+20)>w ) dx = -dx;
    if( (y-20)<0 || (y+20)>h ) dy = -dy; 
    // Apply delta time
    x = x + dx * delta;
    y = y + dy * delta;
    context.clearRect(0, 0, w, h);
    context.beginPath();
    context.fillStyle="#B76EB8";
    context.arc(x,y,20,0,Math.PI*2,true);
    context.closePath();
    context.fill();
}
// Uset setInterval because it will "reprime" the next timeout
// callback faster and more consistently.
setInterval(draw, interval);

请注意,更改间隔延迟会使动画更平滑,但它不会影响球的整体移动速度(由于边缘碰撞的处理方式,这有点像谎言)。尝试将间隔从20更改为10、50、100,然后观察结果。

如果你想以动画中较慢的移动为代价来减少"抖动",那么设置dx&dy==1。

通过这种方式,用户可以看到球以小的增量移动,而不是"跳跃"。

您可以考虑使用requestAnimationFrame来运行动画循环。它会给你一个时间戳,你可以用它将动画限制到每秒不同的帧:

以下是示例代码:http://jsfiddle.net/m1erickson/Y9bYv/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" />
<script src="http://code.jquery.com/jquery.min.js"></script>
<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>
<script>
    $(function(){
        var canvas=document.getElementById("canvas");
        var context=canvas.getContext("2d");
        var x=100;
        var y=200;
        var dx=1;
        var dy=1;
        var start;
        var fps=30;
        var delay=1000/fps;
        requestAnimationFrame(animate);;
        function draw(){
          context.clearRect(0,0, 300,300);
          context.beginPath();
          context.fillStyle="#B76EB8";
          // Draws a circle of radius 20 at the coordinates 100,100 on the canvas
          context.arc(x,y,20,0,Math.PI*2,true);
          context.closePath();
          context.fill();
        }

        function animate(time) {
            requestAnimationFrame(animate);
            if(start===null){start=time;}
            var elapsed=time-start;
            if(elapsed<delay){return;}
            draw();
            start=time;
            x+=dx; 
            y+=dy;
            if(x<20){ dx=-dx; x=20; }
            if(x>280){ dx=-dx; x=280; }
            if(y<20){ dy=-dy; y=20; }
            if(y>280){ dy=-dy; y=280; }
        }
    }); // end $(function(){});
</script>
</head>
<body>
    <canvas id="canvas" width=350 height=350></canvas>
</body>
</html>