您将需要采取一种方法,根据自上一帧以来经过的时间以及您想要以每单位时间的距离单位制作动画的速度来制作动画。
计算经过的时间时必须非常小心;仅仅因为您计划setInterval
每毫秒触发一次n
,并不意味着您的代码将在那个时间触发。更糟糕setInterval
的是,无论如何都有 4ms 的最小延迟。真的!而是依赖代码运行时的时钟。
更好的是,现代浏览器有一个方法叫做requestAnimationFrame()
,每当重绘即将发生时调用一段代码。您向它传递一个回调,它会使用时间戳作为第一个参数调用该方法。
// Find your browser's implementation of requestAnimationFrame
window.requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
// The update method
var update = function(timestamp) {
context.clearRect(0, 0, canvas.width, canvas.height);
// How much time has elapsed since the start of the animation?
var elapsedTime = timestamp - startTime;
// How far have we moved at that time?
var distanceTravelled = elapsedTime * speed;
if (distanceTravelled >= totalDistance) distanceTravelled = totalDistance; // Don't overshoot
// How far have we moved in each component?
var distanceTravelledX = xPerUnitDistance * distanceTravelled;
var distanceTravelledY = yPerUnitDistance * distanceTravelled;
// Move there!
this.x = Math.round(origin.x + distanceTravelledX);
this.y = Math.round(origin.y + distanceTravelledY);
// Draw!
this.drawBoid();
if (distanceTravelled < totalDistance) {
// Schedule update to be called just before the next repaint
requestAnimationFrame(update);
}
}
// The distance you want to move
var distance = 1; // In distance units
// Speed you want to move at
var speed = 0.005 / 1000; // In distance units per millisecond
// Storage for the time when your animation started
var startTime;
// The start point, in distance units
var origin = {
x: 0,
y: 0
};
// The destination, in distance units
var destination = {
x: 100,
y: 75
};
// Distance to travel
var deltaX = (destination.x - origin.x);
var deltaY = (destination.y - origin.y);
var totalDistance = Math.sqrt( Math.pow(deltaX, 2) + Math.pow(deltaY, 2) );
// Storage for the contribution of each component per unit distance
var xPerUnitDistance,
yPerUnitDistance;
if (totalDistance > 0) {
// Start animating!
xPerUnitDistance = deltaX / totalDistance;
yPerUnitDistance = deltaY / totalDistance;
// Get the start time
startTime = window.performance.now ?
// Some browsers use high-precision timers
(performance.now() + performance.timing.navigationStart) :
Date.now(); // A fallback for those that don't
update(startTime);
}
更新:Adam指出Chrome 使用高精度计时器。代码已更新。