Using requestAnimationFrame for canvas element loops
When making any kind of HTML canvas application there is often a need to have some kind of main update loop where the state of a model is updated, and then rendered using some code that can be thought of as a kind of view when drawing to the canvas elements context. Unless the project is completely event driven there will typically be a need to have a way to run the same method over and over again. There is more than one way to go about having a main app loop with a canvas project, but one such option that might be the best choice these days is the requestAnimationFrame method.
For the most part the request animation frame method is the one you will want to go with when it comes to anything involving canvas elements and an app loop. Generally the other options such as the setTimout and setInterval methods are only used for other environments outside of the main event loop of a front end project, such as webworker, or doing something with nodejs.
1 - Request Animation Frame basics
- These source code examples are on Github
1.1 - Basic request animation frame method example
I then have my main app loop that makes used of the request animation frame method. Inside the body of this loop method I call the request animation frame method, and pass the loop method itself as the first argument to the method. I then do what I want to do for a single frame such as add a fixed delta value to the x variable, and also maybe used the modulo operator as a way to get the x variable to loop back to zero when it comes out of bounds. There is then the question of drawing to the context using this x variable such as using the clear rect method of the 2d drawing context, followed by the fill rect method as a way to draw the box.
1.2 - The Style API and moving something by pixels per second with requestAnimationFrame example
So I have an HTML document, and a div element with fixed positioning set, along with some additional fixed style with in-line style. In a script tag I have some variables that will store things like the last time the loop updated, a reference to the div element I want to move, and the current position, and pixel per second rate of movement.
I then have the loop method, which is the method that I will be using with request animation frame, as such there will be a time stamp given via the first argument of the loop method. This time stamp value will just be a number value in milliseconds of the current time. So it is just a way to help keep me from having to create a new date object in each call of the loop function. I can then use this time stamp value with my last time value to get the number of seconds that have passed sense the last update. This seconds value can the be used as a way to update the state of a value by time rather then the rate at which the function calls.
1.3 - Why requestAnimationFrame.
The request animation frame method differs from the other options in that it is generally the best way to go about making an app loop in a front end environment. However in some environments and situations it is not available, or the other ways of doing so might still be more appropriate. There is also having a project that is event driven where the view only updates when an event such as a mouse click happens.
1.4 - Why not requestAnimationFrame?
Browser support is pretty good with requestAnimatinFrame, but the other options have been around much longer. If you really care about pushing backward compatibility back far that can easily be fixed with a polly fill. In addition requestAnimationFrame can not be used in a web worker environment, as such the other options mentioned are all that can be used in that kind of environment. Also requestAnimationFrame is very much a front end thing only, so if you make full stack applications with node.js you are limited to the other options.
2 - Capping a seconds delta value
On thing that has come up that I think I should write about more in an advanced section is making sure to set a cap on a seconds delta value for projects where doing so might be a good idea. This a for the most part only a problem some times when it comes to switching between tabs in a browser, and ending up with a large amount of time between frames. In these kinds of situations I can end up with a large delta value for the seconds value that is used to update the current properties of a model. In some projects this might nt be a problem, it might even be what I want to happen actually. However in order projects it could present a problem where time is being used to update the state of objects as an object will just end up jumping an extreme distance between frames if i do not set some kind of max seconds delta value.
So in this section I will be going over this capping of a seconds delta value in detail.
2.1 - Basic seconds capping example
So the basic idea with this is to make a request animation frame powered main app loop like always, and do the usual bit where I have a secs value that is a delta amount of time that has passed sense the last frame update in seconds, only setting a cap for what the max of this value should be if any. One way would be to just us a ternary operator to set a cap for secs, so in the event that it goes over it will be set to that cap, else the value below it will be used.
3 - Simple animation loop example of requestAnimationFrame
3.1 - The model.js file that creates and updates the state
3.2 - The draw.js file that draws the current state to a canvas element
3.4 - The html
When I open the index.html file in my browser I get a looping animation with a ball moving out from the center of the canvas out to the edge of the canvas and back again as expected. There is a great deal that I might add and change here and there, and in time when I come around to editing this post again I might make those changes. However I think for this example at least there is not that much more to do as I just wanted and example that is a very basic project example that is just a simple looping animation, and this is more or less what that is.
4 - Conclusion
So request animation frame is the method of choice that I always go with when working out a canvas example of any kind, or to do anything that can be a kind of HTML animation in general actually when it comes to CSS effects. I have found that it is generally a better choice than any other options such as set time out or set interval methods, as the request animation frame is designed for this sort of thing in mind rather than just simply updating a model that does not need to be rendered right alway.