First, here's what the Sierpinski triangle looks like:
What is the Sierpinski Triangle?
The Sierpinski Triangle is a Fractal, Making it Naturally Recursive
One initial thing to notice about the Sierpinski triangle is that every triangle is composed of smaller, identical triangles. Those triangles are also made up of even smaller, identical triangles, which are also made up of more triangles, and so on.
This property in which the Sierpinski triangle is made up of identical, scaled-down copies of itself makes it a fractal in mathematics. Fractals are shapes that are made up of scaled down copies of themselves. The Sierpinski triangle is actually arguably one of the most famous fractals that exist, along with Pythagoras Trees, the Mandelbrot set, and more.
The fact that fractals are made up of copies of themselves makes them naturally recursive, and it tends to be simpler to programmatically generate fractals recursively as supposed to using an iterative approach.
The Sierpinski Triangle Only Uses Equilateral Triangles
Next, notice how the Sierpinski triangle is made up of a single shape: the equilateral triangle. This is not a coincidence, and it is in fact one of the reasons the Sierpinski triangle is a notable mathematical figure.
The Sierpinski triangle takes advantage of a property of equilateral triangles: that they are one of the only shapes that can be made up solely by scaled down versions of itself, where a large equilateral triangle can be made by tesselating four equally smaller equilateral triangles. This makes them uniquely positioned to be the centerpiece of simple fractals, since it is intuitive to encompass smaller copies of an equilateral triangle inside a larger one.
This also makes it possible for fractals based on equilateral triangles, like the Sierpinski triangle, to be composed of only one shape. Other polygon-based fractals that don't use equilateral triangles often include several different shapes.
Setting Up the HTML and Canvas Element
Let's start by setting up the
canvas element and basic HTML markup:
Note that the width and height variables in the canvas represent the inner dimensions of the canvas, not necessarily its size on the page. This means it can be resized in the future to fit different screen sizes, while maintaining its inner dimensions of 1000px by 1000px.
Since equilateral triangles are the only shape used in the Sierpinski triangle, it makes sense to write a utility function to draw a given equilateral triangle on the canvas at a specified position and of a specified size.
This function will take in two arguments: the position of the bottom left vertex on the triangle (
pos), and the length of the sides of the triangle (
To create polygons in HTML5 canvas, there are several functions to move to positions on the canvas, draw a path around an area of the canvas, and fill in that area. These include:
context.closePath()— create and close a path; commonly used with
context.fill()after closing the path
context.moveTo(x, y)— move to a position on the canvas.
context.lineTo(x, y)— move to a position on the canvas while drawing a line from the current position.
context.fill()— fill the most recent canvas path.
Creating a triangle simply means identifying the positions of the three vertices, drawing a path around those vertices, and filling the drawn area with a color. Identifying the positions of the vertices is pretty intuitive. Below is a visual showing the positions of the vertices. Note that the height of an equilateral triangle is mathematically equal to as
sin(Pi/3) * sidelen.
With the positions of the vertices done, here's what the function to create an equilateral triangle on the canvas would look like:
Implementing an Algorithm to Generate the Sierpinski Triangle
Now that the canvas and HTML has been set up and the
createTriangle utility function has been written, we can start implementing an algorithm to generate the Sierpinski triangle.
Since fractals are naturally recursive, we'll use a recursive approach to generate the entire triangle.
First, recall that every triangle in the Sierpinski triangle is made up of three smaller triangles, one on the left, another on the right, and a final one on the top. Each smaller triangle is a copy of the outer triangle, the Sierpinski triangle. So, simply create a smaller Sierpinski triangle inside of each of the three triangles, and then more smaller Sierpinski triangles inside of those, and so on. Technically, the Sierpinski triangle repeats forever, but for visualizations like this, a stopping point should be defined when there have been enough repeats that the smallest triangles are hard to make out. At this point, filling in the smallest triangles acts as an effective substitution of repeating further.
To create this stopping condition, a variable called
depth can be used.
depth would represent the amount of times the program should continue repeating the fractal.
depth should start at a certain value and decrease for every repeat, and every smaller Sierpinski triangle created. Once
depth reaches zero (the base case), the program would stop and fill in the three triangles instead of continuing to repeat the fractal.
To create this functionality, let's create a function called
createSierpinskiTriangle which takes the position of the Sierpinski triangle to generate, its side length, and the depth. The function should identify the positions of the three inner triangles, draw them if depth is equal to zero, or call
createSierpinskiTriangle on the three inner triangles if the depth is greater than zero.
Here's what this would look like:
To call the function, draw the Sierpinski triangle at the bottom left of the canvas (
(0, 1000)) with a side length of
1000px (the width of the canvas) and a depth of
Here's the result:
Try increasing the depth, and you should see that the triangle gets more and more detailed. Increasing the depth by one will result in three times the amount of total triangles to be drawn, so very high depths like 20 might not be performant since the canvas would have to draw 3^20 (~3.5 billion) triangles.
Downloading the Generated Triangle From the Canvas as a PNG
Now that we've generated the triangle recursively, one thing you may want to do is download the generated Sierpinski triangle as an image on your computer. Luckily, this is very simple to do in HTML5 Canvas.
First, the canvas must be converted to a data URL. If you're not familiar with data URLs, here's a simple definition:
A data URL is a URL scheme that allows data and files (images, audio files, etc.) to be respresented in a single URL containing all of the data. For example, if one wanted to include an image on a website, you would add the image to the web server and link to it in the HTML. With data URLs, the data URL contains the contents of the entire file, so it can simply be put into the HTML directly. This is useful in canvas because we want to export the image without it having a specific public URL, and data URLs allow that to be done.
The contents of the
canvas element can be converted to a data URL with the
Next, let's download the data URL into the user's machine. In HTML, downloading a file is done by clicking a link and specifying the
download attribute. For example, here's how someone would download an image as
myimage.png when the user clicks a link:
<a href="image.png" download="myimage.png">download!</a>.
download attributes, and artificially clicking on it.
Here's what this would look like:
To create a download button, adding a simple HTML button with the
onclick attribute set to the
downloadCanvasContents function should suffice.
Final Code and Conclusion
I hope you enjoyed this article, and found it interesting in generating the Sierpinski triangle with HTML5 canvas. For more mathematical background on the Sierpinski triangle and its history, I would recommend taking a look at the Sierpinski Triangle Page on Wolfram MathWorld and the Sierpinski Triangle Wikipedia Page.
Thanks for scrolling.
— Gabriel Romualdo, November 20, 2020