When working with HTML5 Canvas, we're constantly interacting with the canvas context object, which contains an abundance of cool styling properties and drawing methods. For a typical block of code that draws something onto the canvas, we draw a path, set a handful of context properties to style whatever it is we're drawing, and then use methods like fill() and stroke() to actually draw things onto the canvas. Piece of cake, right?
But what happens if we're creating large, complex canvas applications, and we have lots of methods and functions that draw things onto the canvas which can be executed in any order? We certainly don't want styles from different parts of our code base leaking into other parts of the code base. Here's an example:
So what can we do do? Should each of our methods and functions reset the context styles like a CSS reset for each function? Although this could be achievable by creating a resetStyles() function which loops through all of the styling properties and sets them to their default values, it seems a bit odd to constantly reset all of the style properties each time a function call is made. Is there a better way?
Style Scope Induction
The HTML5 Canvas State Stack: A Diamond in the Rough
One of the most powerful, and probably the most overlooked features of the HTML5 canvas, is the state stack. The state stack stores snapshots of styles and transformations in a stack data structure via the save() method of the canvas context. What's even more important is that we can also use the state stack to restore snapshots of styles and transformations with the restore() method.
So how can we use the state stack to induce style scope? If we use the save() method at the beginning of a function definition, we can save the state of the canvas context in the state stack. Once the state is saved, we can apply several context styles, draw things, and then restore the state stack back to the initial state with the restore() method. Viola, we've just induced style scope.
Style Scope Induction Example
So let's now use the state stack to fix the previous code example by inducing style scope for each function:
Success! By inducing style scope for each function, the alpha style is now contained in the drawTransparentSquare() function and no longer leaks into the drawSquare() function.