In my last post I shared my Paper Snowflake web app, which allows users to create and share virtual paper snowflakes. There is a significant amount of JavaScript code behind the application, and I’ll take a couple blog posts to explain some of the inner workings. Here I’ll concentrate on how multiple HTML5 canvases are used together to handle drawing and interactivity.
If you haven’t had the chance yet, give the application a try! Since the last post, I’ve added the ability to change background colors. Click here or on the screencap below to open up the application. After you make a snowflake, you can share the image to your computer or share it on Facebook. (It will work on mobile devices, but it’s still not optimized for touch events. That will have to wait for a future version.)
You can also see this flickr set for some of the snowflakes I created with this app.
Using multiple canvases
Although the application is rather simple looking on the surface, there are actually several canvases in use, some on-screen and some off-screen. These canvases are placed on top of each other, or used to cut out shapes from other canvases by changing the globalCompositeOperation. In total there are ten different canvas instances used for various purposes, plus an array of six canvases containing the differently colored gradient backgrounds.
The interactive board
The interactive board (on the right side of the application) containing the folded paper triangle shape is made up of three canvases of equal size layered on top of each other. Layering the canvases is easy using CSS by using absolute positioning and different z-index values, and placing these canvases in one div that can be positioned as desired.
boardBackgroundCanvas
: A colored background canvas, which only changes when the user selects a different background color.polygonLayerCanvas
: This canvas contains the polygon outlines as they are drawn by the user. The graphics consist of vertices (dots) and lines only. The filled in color is drawn into the boardCanvas below.boardCanvas
: A canvas containing the cut out triangle shape, which is white with a transparent background.
Here is an illustration of these three canvases:

When the user draws new polygons on the board (or edits existing polygons by dragging vertices), the cut-out shape is accomplished by drawing an opaque polygon onto the boardCanvas
after setting the globalCompositeOperation to “destination-out”, which preserves existing content in the canvas where it doesn’t overlap drawn image.
The snowflake
When the user presses the “make snowflake!” button, several things happen to draw the snowflake on the left. In total, six canvases are used: two on-screen and four off-screen. These canvases are used together to create the snowflake with a folded-paper shading effect and colored background.
On-screen, a displayBackgroundCanvas
holds a gradient-colored background (explained below), and on top of this is a displayCanvas
holding the snowflake image and its shadow with a transparent background.
Off-screen, a snowflake shape is created by copying the cut-out triangle shape from the interactive board twelve times into a snowflakeShapeCanvas
, using appropriate translations, rotations, and scaling transformations (the geometry of these transformations will be the subject of a future blog post). Once this off-screen snowflake shape is created, this shape is used to “cut out” the same shape from a textured and shaded paper image which is stored in a separate off-screen paperShadingCanvas
(this shading is created programmatically – see below). This time we use the “destination-in” globalCompositeOperation
, which preserves existing content in the canvas only wherever it overlaps the newly drawn image. We first draw the paperShadingCanvas
into an off-screen bufferCanvas
, set the globalCompositeOperation
to “destination-in”, then draw the snowflakeShapeCanvas
onto the bufferCanvas
. See the illustration below:

Once we have this properly shaded snowflake stored in the buffer canvas off-screen, we assemble the on-screen snowflake image by drawing a shadow in another off-screen canvas first (explained below), then drawing this shadow and the shaded snowflake from the buffer into the on-screen displayCanvas
. Behind this displayCanvas
is a displayBackgroundCanvas
, which contains the gradient colored background.
The shadow
Although the HTML5 canvas has built-in methods for drawing shadows, at the time of this writing it doesn’t work with bitmaps with transparency in current version of Chrome due to a bug (see here). So for cross-browser consistency I decided to draw my own shadows. Here is where the StackBlur for Canvas by Mario Klingemann (a.k.a. quasimondo) came to the rescue! (I changed the code slightly so it would take a canvas context as an argument rather than a canvas object). I wrote a makeShadow()
method which copies the snowflakeShapeCanvas
to a new canvas, while changing the color to a semi-transparent gray shadow color. This canvas is then blurred using quasimodo’s StackBlur. This shadow canvas can then be copied into the on-screen display canvas with an offset, creating the shadow effect behind the snowflake.
The paper shading
This web app uses no images loaded at runtime. The paper shading is drawn programmatically at the beginning and stored in an off-screen paperShadingCanvas
, using the following method that I came upon after some experimentation, and which again uses quasimondo’s StackBlur:
- Gray wedges drawn of various shadings to suggest folded paper,
- noise is added to this image by randomly shifting pixel colors
- The image is blurred with StackBlur by Quasimodo
- more noise (subtler this time) is added.
The gradient backgrounds
The background colors behind the snowflake may look solid, but they are actually subtle gradients, which I found to look nicer. But the gradients are subtle enough that a “banding” effect could be noticeable. So I used my dithered gradients for the HTML5 canvas that I posted at this blog here. (See the radial version here, and dithered gradients for Processing here).
Since the code for drawing these gradients is computationally intensive (although still rather fast), the gradient backgrounds are drawn once at the beginning of the application and stored in an array of canvases, then drawn into the displayBackgroundCanvas
as needed when the user selects a different color.
More to come!
There is a lot more going on in this application, and I plan on blogging about more of the code in the future. In particular, the use of transformations to create the snowflake symmetries, plus the code used for image saving and Facebook sharing are worthy of further discussion. Stay tuned!
Acknowledgment
My thanks again to Mario Klingemann (a.k.a. quasimondo) for his excellent StackBlur for Canvas!
Used your drag and drop tutorial to begin working with canvas animation. I looked at some of your other stuff which is very impressive. Thank you for the well written tutorials.
November 15, 2015 @ 10:39 pm
|Sorry I never responded! Thank you. Glad you are enjoying the site.
January 10, 2016 @ 3:25 pm
|Its really fun but i played it for hours and now my pinkie hurts
January 12, 2018 @ 6:39 pm
|So this weekend i went to school and my thecer said that ima send u a wed site on zoom i said ok and it was this wed so isaid thx she said np so i cheak some stuff i said ima make a snow flake and i found this i really wanna make one by my self and i cant bc i dont have to time i have to clean and stuff i cant no more i really want to me in it
January 16, 2021 @ 6:32 pm
|Thank you for continued access to this. I use the snowflake generator as an assignment in my art class when we have virtual days and can’t be in the physical classroom.
January 26, 2023 @ 5:36 pm
|Happy to know! Thank you for your note!
March 13, 2023 @ 1:54 am
|