Jquery中的加速setInterval

时间:2015-05-31 13:26:25

标签: javascript jquery animation canvas

我正在尝试创建一个弹跳球(在画布上)。如果球在上下起伏时会加速,我会很高兴。不知道如何使用setInterval执行此操作。这是我的代码:

setInterval(function animate() {
    ctx.clearRect( 0, 0, canvas.width, canvas.height);

    if (movement1 === true) {
        dotHeight += 1;
        if (dotHeight >= 100) movement1 = false;
    } else {
        dotHeight -= 1;
        if (dotHeight <= 0) movement1 = true;
    }
        ctx.beginPath();
        ctx.arc(canvas.width / 2, (canvas.height / 2) + dotHeight, dotSize, 0, 2 * Math.PI);
        ctx.fillStyle = "white";
        ctx.fill();
    }, 4);

这导致线性运动。我希望有一个自然的运动。基本上快速启动并在到达顶部时变慢,反之亦然。

3 个答案:

答案 0 :(得分:2)

基本原理是使用速度变量而不是恒定的高度增量。因此,除了dotHeight += 1dotHeight -= 1之外,您可以在dotHeight += dotVelocity处定义dotVelocity,并在球在空中时将其减去常数值(重力)。

var dotHeight = 0;
var dotVelocity = 3; // start out moving up, like in your example
var gravity = .1; // you can adjust this constant for stronger/weaker gravity

setInterval(function animate() {
ctx.clearRect( 0, 0, canvas.width, canvas.height);

if (dotHeight > 0) { // if it hit the ground, stop movement
     dotVelocity -= gravity;
     dotHeight += dotVelocity;   
}
    ctx.beginPath();
    ctx.arc(canvas.width / 2, (canvas.height / 2) + dotHeight, dotSize, 0, 2 * Math.PI);
    ctx.fillStyle = "white";
    ctx.fill();
}, 4);

答案 1 :(得分:2)

您应该同时拥有speedgravity(或acceleration)变量:

  • speed告诉您在当前更新中移动对象的单位数(此处为像素数)。
  • gravity告诉您每次更新时增加了speed个单位。

您想要一个常量gravity,以便speed在每次更新时增加相同数量的像素。这将为您提供变量speed,以便您的对象(此处为点)在每次更新时移动更长或更短的距离,具体取决于其行进方向。

要使点反弹,只需更改其speed到达地面时的方向。您只需要将其乘以-1,或者相反,您可以将其乘以bouncingFactor-1 < bouncingFactor < 0),以便在每次反弹时失去能量:

enter image description here

在这里你可以看到一个有效的例子:

var canvas = document.getElementById("canvas");
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;

var ctx = canvas.getContext("2d");
var frames = 0; // Frame counter just to make sure you don't crash your browser while editing code!

// DOT STUFF:

var dotSize = 20;
var dotMinY = 0 + dotSize; // Start position
var dotMaxY = canvas.height - dotSize; // Floor
var dotY = dotMinY;
var dotSpeed = 0;
var dotLastBounceSpeed = 0; // You can use this to determine whether the ball is still bouncing enough to be visible by the user.

var center = canvas.width / 2; // Try to take every operation you can out of the animate function.
var pi2 = 2 * Math.PI;

// WORLD STUFF:

var gravity = .5;
var bounceFactor = .8; // If < 1, bouncing absorbs energy so ball won't go as high as it was before.

// MAIN ANIMATION LOOP:

function animate() {
  ctx.clearRect( 0, 0, canvas.width, canvas.height);

  ctx.beginPath();
  ctx.arc(center, dotY, dotSize, 0, pi2);
  ctx.fillStyle = "red";
  ctx.fill();

  // First, dotSpeed += gravity is calculated and that returns the new value for dotSpeed
  // then, that new value is added to dotY.
  dotY += dotSpeed += gravity; 
  
  if(dotY >= dotMaxY ) {
    dotY = dotMaxY;
    dotSpeed *= -bounceFactor;  
  }

  var dotCurrentBounceSpeed = Math.round(dotSpeed * 100); // Takes two decimal digits.
  
  if(frames++ < 5000 && dotLastBounceSpeed != dotCurrentBounceSpeed) {
    dotLastBounceSpeed = dotCurrentBounceSpeed;
    setTimeout(animate, 16); // 1000/60 = 16.6666...
  }
  else alert("Animation end. Took " + frames + " frames.");
}

animate();
html, body, #canvas {
  position:relative;
  width: 100%;
  height: 100%;
  margin: 0;
  overflow:hidden;
}
<canvas id="canvas"></canvas>

您还应该考虑使用setTimeout requestAnimationFrame。来自MDN doc:

  

Window.requestAnimationFrame()方法告诉浏览器您   希望执行动画并请求浏览器调用   指定在下次重绘前更新动画的函数。该   method将一个回调作为一个参数,在之前调用   重绘。

var canvas = document.getElementById("canvas"); canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; var ctx = canvas.getContext("2d"); var frames = 0; // Frame counter just to make sure you don't crash your browser while editing code! // DOT STUFF: var dotSize = 20; var dotMinY = 0 + dotSize; // Start position var dotMaxY = canvas.height - dotSize; // Floor var dotY = dotMinY; var dotSpeed = 0; var dotLastBounceSpeed = 0; // You can use this to determine whether the ball is still bouncing enough to be visible by the user. var center = canvas.width / 2; // Try to take every operation you can out of the animate function. var pi2 = 2 * Math.PI; // WORLD STUFF: var gravity = .5; var bounceFactor = .8; // If < 1, bouncing absorbs energy so ball won't go as high as it was before. // MAIN ANIMATION LOOP: function animate() { ctx.clearRect( 0, 0, canvas.width, canvas.height); ctx.beginPath(); ctx.arc(center, dotY, dotSize, 0, pi2); ctx.fillStyle = "red"; ctx.fill(); // First, dotSpeed += gravity is calculated and that returns the new value for dotSpeed // then, that new value is added to dotY. dotY += dotSpeed += gravity; if(dotY >= dotMaxY ) { dotY = dotMaxY; dotSpeed *= -bounceFactor; } var dotCurrentBounceSpeed = Math.round(dotSpeed * 100); // Takes two decimal digits. if(frames++ < 5000 && dotLastBounceSpeed != dotCurrentBounceSpeed) { dotLastBounceSpeed = dotCurrentBounceSpeed; //setTimeout(animate, 10); window.requestAnimationFrame(animate); // Better!! } else alert("Animation end. Took " + frames + " frames."); } animate();相同的示例:

html, body, #canvas {
  position:relative;
  width: 100%;
  height: 100%;
  margin: 0;
  overflow:hidden;
}
<canvas id="canvas"></canvas>
setTimeout

如您所见,您只需要更改一行代码!但是,如果浏览器不支持requestAnimationFrame,您可能需要requestAnimationFrame才能回到requestAnimationFrame

您可以在polyfill中详细了解bundle。它解释了基础知识以及如何设置自定义帧速率。

答案 2 :(得分:1)

您可以使用age_range变量而不是常量age_range来确定&#34; far&#34;移动球,像这样:

{{1}}