logoEbreiny

Back to Home

showcase

JavaScript Canvas Shape Engine

11/10/2024

I love making fun visual effects in design, whether that be in my pixel art, on websites, or anywhere else. While browsing other sites for inspiration, I saw one site that had these fun particles and shapes jump out when you click it and I immediately wanted to make something like it.

Where to Start

There are many ways of creating an effect similar to this one. However, I recently had been using and gotten pretty experienced with HTML canvas elements from my Pixel Art Avatar Creator project. Since this was the case, I decided to use a canvas.

In case you are unfamiliar, a canvas is an element that allows you to draw on it. You can draw any shape in any color, erase sections, or clear the entire board. It works very similar to a real-life whiteboard.

What to Draw

One of my goals with recreating this button was to be able to draw any shape that I wanted. However, this is where it starts to get a bit complicated. There a couple of ways to draw shapes onto a canvas, but none of them really achieved exactly what I wanted. I wanted my shapes to be able to turn and move and scale independently of one another. Since this was the case and after a lot of research, I decided to create a system of my own.

The Shape Engine

For my shapes, I will be using SVGs (scalable vector graphics). These are basically images that can be scaled to any size and not lose any quality. This is because the data is stored as paths rather than just colors of an image. For example, an SVG heart might look something like this:

"M 0 -2 C -1 -4 -4 -2 -2 0 L 0 2 L 2 0 C 4 -2 1 -4 0 -2 Z"

Now, this doesn't look anything like an image, but how it works is that each letter and set of numbers correlate to a command and a point in space. This SVG starts off with the capital letter 'M,' which means 'Move To.' In this case, we are moving to the position (0, -2) to start our path. I won't dive to deep into the rest, but the letter 'C' means 'Curve To,' the letter 'L' means 'Line To,' and the letter 'Z' simply means to close the shape. If you want to play around with making SVGs, I have been using a website named SVG Path Editor to do so.

Ok, so we have an SVG now and understand how it works. How does this help us? With canvases, you are able to draw lines and curves in a very similar way. My idea was to programmatically break up the SVG code you see above into its separate parts and then use that data to draw each individual line and curve in JavaScript. And the best part, is after a lot of time and coding, the idea actually worked! However, this did not mean that I was done.

Transforming the SVG

See, we now have the ability to draw any SVG shape to a canvas, but we can't move, rotate, or scale it. This is where things got really complicated. I needed a way to use the data I had in a way that would let me modify it but retain the same shape. What I ended up doing was converting each point used to draw the SVG into two bits of data, its angle relative to a center point and the distance from the that same center point.

Finding the distance is simple enough. There is a simple formula that looks like the following:

distance = Math.Sqrt(Math.Pow((x2 - x1), 2) + Math.Pow((y2 - y1), 2))

Finding the angle is a bit tougher. This is where I had to break out some old trigonometry knowledge. We need to convert a position into an angle around a center point. Our center point in this case is 0, 0, which makes things nice and simple. To convert a point into an angle, we will be using the 2-argument arctangent (atan2). This handy function will actually return the exact data that we are looking for. The only thing to note is that the output will be in radians rather than degrees.

Why would I do this? Well, with an angle and to rotate our shape, all that would need to be done is to modify the angle equally for every point and then draw the shape again. This way, the SVG retains its shape and can be drawn at any angle. As for scaling, if I multiply all of the distance values by any number, this will change the shapes size. Finally, for moving the shape, all I need to do is move the origin as each point is drawn relative to the origin's position.

Image

Putting it All Together

We are now able to draw any shape we want at any location, rotation, or scale on a canvas. The last step is to make some effects! I used the requestAnimationFrame() function in JavaScript to do this. While it isn't necessarily the best way to do things since the speed of the animation will change depending on your refresh rate, I thought it would suffice for now.

To see some of the effects that I have made, you can visit my Canvas Shape Engine page. You can also see an original older version on CodePen (although that one isn't reading SVGs).

Back to Home