JavaScript - canvas animations
In this article, we would like to show you how to make canvas animations using JavaScript.
Once the shape is drawn it stays that way. In order to move it, we need to redraw the shape and everything that was drawn before,
To draw a frame you need to:
- clear the canvas,
- save the canvas state,
- draw animated shapes,
- restore canvas state.
In this example, we create an animation using requestAnimationFrame()
method.
With these approaches, the frames are being drawn at the most appropriate moment for the browser.
This example doesn't contain any logic controlling the speed of the animation.
xxxxxxxxxx
<html>
<head>
<style>
#my-canvas { border: 1px solid gray; }
</style>
</head>
<body>
<canvas id="my-canvas" width="300" height="100"></canvas>
<script>
var canvas = document.querySelector('#my-canvas');
var context = canvas.getContext('2d');
var squareX = 0;
var squareY = 35;
var squareSize = 30;
function drawFrame(timestamp) {
// Hint: in practice it is good to use timestamp to control animation speed
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = 'red';
context.fillRect(squareX, squareY, squareSize, squareSize);
squareX += 2; // 2px per frame drawing
if (squareX <= canvas.width - squareSize) {
requestAnimationFrame(drawFrame);
}
}
window.requestAnimationFrame(drawFrame);
</script>
</body>
</html>
Using lastTimestamp
and currentTimestamp
we are able to calculate how much time has passed since the last frame was drawn, so we can draw a smooth animation.
xxxxxxxxxx
<html>
<head>
<style>
#my-canvas { border: 1px solid gray; }
</style>
</head>
<body>
<canvas id="my-canvas" width="300" height="100"></canvas>
<script>
var lastTimestamp = null;
function requestFrame(currentTimestamp) {
if (lastTimestamp === null) {
lastTimestamp = currentTimestamp;
} else {
var result = drawFrame(currentTimestamp - lastTimestamp);
if (result === false) {
return;
}
lastTimestamp = currentTimestamp;
}
window.requestAnimationFrame(requestFrame);
}
window.requestAnimationFrame(requestFrame);
// Usage example:
var canvas = document.querySelector('#my-canvas');
var context = canvas.getContext('2d');
var squareX = 0;
var squareY = 35;
var squareSize = 30;
function drawFrame(dt) { // dt returns elapsed time in milleseconds since last drawing
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = 'red';
context.fillRect(squareX, squareY, squareSize, squareSize);
squareX += 0.1 * dt;
if (squareX > canvas.width - squareSize) {
return false;
}
}
</script>
</body>
</html>
In this example, we present an alternative solution that clears the canvas
and draws the square with a changed position (moved by 1
px) every millisecond.
xxxxxxxxxx
<html>
<head>
<style>
#my-canvas { border: 1px solid gray; }
</style>
</head>
<body>
<canvas id="my-canvas" width="300" height="100"></canvas>
<script>
var canvas = document.querySelector('#my-canvas');
var context = canvas.getContext('2d');
var squareX = 0;
var squareY = 35;
var squareSize = 30;
var interval = setInterval(function() {
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = 'red';
context.fillRect(squareX, squareY, squareSize, squareSize);
squareX += 1;
if (squareX >= canvas.width - squareSize) {
clearInterval(interval);
}
}, 10);
</script>
</body>
</html>