JavaScript Canvas – Animation

Page 1 of 3

You can use Canvas animation is simple – or is it? Just keep drawing the pictures. In this excerpt from a chapter in my new book on JavaScript graphics, we take a look at how it works.

Now available as a paperback or ebook from Amazon.

Bitmap JavaScript graphics
With canvas


  1. JavaScript graphics
  2. Getting started with Canvas
  3. Drawing paths
    Extract: Basic paths
    Extract: Bézier curves
  4. Stroke and filling
    Extract: Contour properties
    Extract: Filling and holes
  5. Transformations
    Extract: Transformations
  6. Text
    Extract: text, typography and SVG
    Extract: Unicode
  7. Cutting, composition and effects
    Extract: basic cutting and composition
  8. Generate bitmaps
    Extract: Introduction to bitmaps
    Extract: Animation **NEW!
  9. WebWorkers & OffscreenCanvas
    Extract: OffscreenCanvas
  10. Bit manipulation in JavaScript
  11. Typed arrays
  12. Files, blobs, urls and fetch
    Extract: Blobs and files
    Extract: read / write local files
  13. Image processing
    Extract: ImageData
    Extract: API Filter
  14. WebGL 3D
  15. 2D WebGL
    Extract: WebGL Convolutions

In the book but not included in this excerpt:

  • The image object
  • Draw a picture
  • ImageBitmap


One of the main uses of Canvas is to create simple animations. The principle of animation is well known. You display a picture for a short time, change the picture, show the new picture and so on. How fast should you display new images? The answer is that a new image every 1 / 25th of a second usually creates an impression of movement, but in most cases programs try to display a new image every time the display frame is updated. by the material. This is the fastest rate possible and generally produces smooth animation.

JavaScript has a method that will call a function as soon as possible after each image refresh. The requestAnimationFrame method will call a function you provide so that it has as much time as possible to update the graphics before the next paint update to generate the frame. The function is:

var id = requestAnimationFrame(animate);

The returned identifier can be used to cancel an animation using:


The function, called animate in this example, receives a single parameter which is the time, usually in milliseconds, at the start of the frame, measured from the loading of the web page.

The requestAnimationFrame method is fairly straightforward to understand, but it does have a few subtle points. The first is that the animate function must end with a call to requestAnimationFrame if it is to be called for each frame. That is, requestAnimationFrame executes the function once at the start of the next frame. The time the function has to execute is as much time between frames as the JavaScript engine can give it. Once the frame is finished, the engine processes all the pending events and tasks, then calls the requestAnimationFrame function, that is to say animate in our example.

The function can run as long as it wants, but if it runs longer than the time until the next frame, it misses the update and all the changes are visible in the next frame. after the end. If there are multiple requestAnimationFrame functions pending, they all get the same timestamp, which is only an indicator of which frame they are supposed to prepare for. As you would expect, if one of the functions takes longer than one frame, the next frame is skipped.

All this means that it is advisable to limit your requestAnimationFrame functions to one per application and to limit the processing time.

How short is short?

The simple response is less than 16 ms.

If you try the following program:

function animate

you will be able to see a cross-frame time sample for the particular browser you are targeting.

For Chrome, at the time of writing, the results were mostly 16.66 milliseconds, which is close to the time between frames for 60 fps. However, sometimes you will see values ​​of 50ms and even 500ms. These are caused by the browser having to do something other than respond to your request. There is nothing you can do about these issues, and by and large they go undetected by users.

Draw or BitBlt?

There are two ways to get a shifting image between frames. You can draw your image using paths and so on or you can BitBlt a bitmap on the canvas. BitBlt, pronounced bit-blit, is the abbreviation for bit-block operation and is often abbreviated to blit. This is essentially a low-level copy of a group of bits stored in memory to another area of ​​memory and, as we just found out, we can do this with drawImage.

To compare the two methods, let’s first animate a simple rotating square using drawing methods, then blitting.

To draw a rotating square, all we need to do is adjust the coordinate system so that we revolve around the center of the square, see Chapter 5.

var inc = 0.1;
var ctx = document.body.appendChild(
createCanvas(600, 600)).getContext("2d"); var path = new Path2D(); path.rect(-25, -25, 50, 50); ctx.translate(100, 100); requestAnimationFrame(animate);

The animation function simply erases the canvas, rotates the coordinate system, and draws the path:

function animate
  ctx.clearRect(-100, -100, ctx.canvas.width,
ctx.canvas.height); ctx.rotate(inc); ctx.fill(path); requestAnimationFrame(animate); }

If you try the program, you will see a smoothly rotating square. There are a few minor issues with this approach – it is especially important to remember what the current coordinate system is. Generally, this can be avoided by using backup and restore.

The same animation obtained by blitting requires a single frame of sprite animation. An animated sprite image is a single bitmap with a shape, the sprite, drawn in different positions for animation. In this case, 16 sub-images are sufficient:


It doesn’t really matter how this bitmap is created. You can use a bitmap editor or you can write a program to generate it. The basic idea is to load the bitmap and use requestAnimationFrame to display each cell of the animation in turn:

async function getImage(url) {
 function animate
     var cellx = 76;
     var celly = 76;
     var cellno = 16;
     ctx.clearRect(100, 100, cellx, celly);
     ctx.drawImage(img, cellx * i, 0, cellx, celly,
                              100, 100, cellx, celly);
     i = i % cellno;
 var img = new Image();
 img.src = url;
 await imgLoaded(img);
 var i = 0;

In this case, the getImage function now acts more like an asynchronous main program – which often happens. The animate function is defined within it so that it can access the local variables of getImage. The getImage function collects the sprite images, then calls requestAnimationFrame to start the animation. The variable i defines which cell of the bitmap is displayed.

If you try the program, you will find that you get smooth animation, but not as smooth as the first version. To get an even smoother animation, you would need more cells.

The main difference between the two approaches is that the drawing method takes as much time as it takes to make the paths involved. The BitBlt method always takes the same time, regardless of the complexity of the sprite. The drawing method has the advantage of being dynamically editable, while in most cases blitting is limited to sprites that you have already created.

Source link

Previous Global Breast Tissue Expanders Market Huge B2B Opportunities 2021_27 Allergan, Mentor Worldwide, GC Aesthetics - KSU
Next Stevens Auction Company's May 15 Spring Antiques Estate Auction Showcases Rare and Important Items