The above function takes two parameters. The first needs to be a DOM element, preferably empty. The dimensions of this DOM element will determine the virtual size of the canvas element we’re generating and appending to the DOM.
The Render Function
The second parameter is a render function. This is where you’ll put all of your draw logic. The render function will be passed configured canvas and context objects that can be used to draw. If you want to make your drawings relative to the canvas size, you can use canvas.clientWidth / 100 and canvas.clientHeight / 100 as percentage units.
The render function can be fired manually via this.update, and will also be fired on window.resize events to allow for responsivity. (Note: for more CPU intensive canvas elements, you’ll likely want to debounce calls to the render function to avoid excessive CPU utilization).
The Rest of the Create Module
The first task the create function does is create a canvas element in the document scope. Then, it initializes some local variables, w and h by measuring the client dimensions of the DOM node that was passed into the function as parent. Next, we create a 2D canvas context on the canvas element we created and give it an identifier (an integer that is equal to the number of keys currently in the registry, incremented by one).
The next discrete action this function performs is setting an event listener for the ‘resize’ event. All this does is call the CanvasSingleton.update function and pass in the canvas identifier from the canvas we’re creating.
Next, we set the canvases literal width and height to the measured dimensions multiplied by the devices pixel ratio. The following lines set the canvases style dimensions to the measured dimensions of the parent DOM element. What this means, in effect, is that the canvas is much bigger in memory than it will be rendered, by a factor of the devices pixel ratio. The canvas is compressed by the renderer to the measured size. For devices with pixel ratios higher than 1 (almost everything, nowadays), this means your canvas will be crisp at any pixel density.
The last lines of this function append the canvas element we initialized to the parent element that was passed into the function via parameter, calls the context.scale method with our pixel ratio values to make the high-DPI support work, set the registry entry at context.identifier to be an object containing references to our parent, canvas, render function, listener, and context, call the render function directly once, and then return the context object to the function that called the create function so that code external to this can access the identifier for actions later in the canvases lifecycle.