如何调整动画的速度?

时间:2014-04-25 06:00:53

标签: javascript html5 canvas

我想制作一个弹跳球,我可以在其中调整弹跳速度

这是我的原始代码

 <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);

    })();

  }

使动画更流畅

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

由于

2 个答案:

答案 0 :(得分:1)

超时/间隔应不小于约20毫秒,动画功能应根据 delta-time elapsed 设置动画。这将产生一致的动画(离散位置函数可能更好,但简单的delta时间方法通常可以很好地工作)。

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

考虑this demo

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并观察结果。

答案 1 :(得分:1)

如果你想要更少的&#34;抖动&#34;以动画中较慢的移动为代价,然后设置dx&amp; dy == 1.

这样,用户以较小的增量观看球的移动,而不是#34;跳跃&#34;。

您可以考虑使用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>