For Hacktoberfest this year, I contributed to a project using the
<canvas> element. I was intrigued, as I'd come across it before while I was learning HTML but always thought "Eh, I'll get to that one day...".
What is the
id and dimensions you'd like as attributes, and wraps around a backup image which only displays if your drawing doesn't load:
How to animate the moon
You don't have to animate the
<canvas> element but I thought it'd be a nice challenge. I decided to create a waxing and waning moon animation. My approach was to write a function for each phase and loop through them using
Lay the foundation
Before anything else, every
<canvas> element must start with two things:
First, we select the
<canvas> element in the HTML with its
id and save it in a variable. Second, we create a variable for the context. This is what we actually draw on. Surprise! The
<canvas> element itself is really just a container. This context variable is what we will use in our functions.
I chose a crescent moon as my starting phase. I drew it with a function called
init() and added it as an attribute to the
<body> element we saw before, so that it's called when the page loads.
Repeat with slight variations
I ended up with six very similar functions, so similar that I won't detail each of them here:
Each function calls the next one and
init(). That is how the continuous wax/wane effect is achieved. The only differences are the inner(bezier) and outer(arc) curves of each phase. Really it's only four functions, as
halfMoon() are basically equivalent to
halfMoonWane(). I repeated them because during the waning phase I needed the same shapes but different
setTimeout() function calls.
Challenges and reflections
<canvas> element is no joke. I spent two days working out how to achieve this animation. Granted, it was my first try and I had to do a lot of research and trial and error with tricky math, but it's still a challenging element to work with. Even though I'm glad I got acquainted with it, I can't really think of a situation where I'd want to use it again.
One of the hardest things about it is that you can't see your progress unless you call a method to connect the points you've established (I used
ctx.fill() here, you can use
ctx.stroke() to draw a line instead). It was cumbersome doing that after every line and then deleting them all(except the last one) once I knew what was happening. It makes me wonder if there is an easier way.
I also really wanted the transition between each stage to be a little smoother. I tried speeding up the intervals on
setTimeout() but that didn't give me the effect I was hoping for. I also experimented with
window.requestAnimationFrame(), another method used with
<canvas>, but that made it way too fast by itself. I'm sure there is a way to make it work but I wasn't able to find it after much searching and experimenting.
Finally, since there is a lot of repeated code here, I'm sure there is a more elegant way of achieving this type of animation but in the end it gets the job done and I'm a fan!
Here's a resource for more info on the
<canvas> element and, as always, here's my code if you'd like to inspect in more detail.
Top comments (3)
This looks awesome @gabriellend Thanks for sharing!!
Thank you for reading! :D
how in the world do you figure out the numbers for the bezier curve stuff? T-T