JavaScript Christmas Calendar Tutorial ๐ŸŽ„

freeCodeCamp.org ยท Beginner ยท๐ŸŒ Frontend Engineering ยท1y ago

Key Takeaways

Create a Christmas calendar using JavaScript and HTML canvas, learning about coordinates, basic math, and programming techniques.

Full Transcript

get in the holiday Mood by creating a Christmas calendar with JavaScript and HTML canvas each day of the month of December Dr Ru shared a tutorial on his channel teaching how to procedurally generate a unique christmy icon this video is the entire Christmas tutorial series and it's a great way to learn about modularity reusability and writing consistent code you can even submit your own versions for Dr Ru to showcase at the end of this year this December I'm making a Christmas calendar using vanilla JavaScript and HTML canvas in each one of these days I'm going to procedurally generate a unique Christmasy item because I need icons like these around this time and good free ones are hard to come by I also want to easily scale and color them in different ways I hope you'll follow along and Implement your own versions so I can showcase them in a special video on the 24th you'll practice working with coordinates basic math and various JavaScript programming techniques it's a good project I think to learn about code modularity reusability and how to write consistent code oh and uh I'll be coding without glasses apparently because making one video a day is not enough of a challenge now let's set up the project from scratch and learn how to draw a star oh coding withraw let's code now I'm going to be coding in Visual Studio code and in an empty folder let's create our first file index.html now we begin with basic HTML syntax first the dock type then the HTML opening and closing tags and then the head let's close the head and give the page title December 2024 like so now if you save this file and open it in a browser I'm using Google Chrome it's empty as we expect but here at the top it does show the title of the document so we are good to go now in the body we are going to generate that kind of calendar grid but I'm not going to add all the elements one by one in HTML instead we're GNA be using JavaScript so let me open here a script tag and let's close it as well and in it I want to generate a grid with a given cell size let's say 200 pixels and now we can Loop through all the days starting at day one and all the way to day 24 we increase and we generate a new canvas element for each day like so we're going to be drawing a different item on each one of these canvases eventually now let's set the width to the cell size and the height to the cell size and add these canvases to the document body like so otherwise we won't see anything now if you save and refresh the page you actually still don't see anything but if you open the developer tools inside of this element section you will see that these canvases are there they are just transparent so let's give them a little bit of a style to distinguish them I'm going to go up here in the head section and in the style I will give the canvas element let's start with the background color I'm going to use a light gray like so I'm missing some margins here I'm going to add let's say a three pixel margin like so and let's round the corners a little bit to make it look nicer right and we don't need these developer tools anymore we can see the canvases but of of course we should always keep them open on the console tab so that we can tell if there are any errors on the page always keep the console open when coding now let's fill these cells with something I'm going to add here function called fill cell for the day and the given canvas and I'm going to implement this function down here given an index and canvas element let's first get the reference to the two the drawing context of the canvas like this and I'm going to draw everything in the center of the cell so let's get an XY coordinate of it like so half the canvas width and half the canvas height I also want the items to have a specific size and I could make them the width of the canvas for example but let's scale this down maybe to 60% so that there is some margin around the items as well and for now I'm going to draw a number in each of these cells as a placeholder passing these parameters and let's implement this function down here so given a context and a value at X and Y let's just call the last one size and I'm going to call field text with the value at the XY location save refresh and there are the numbers quite small let's make them bigger and actually use this size parameter so I'm going to set the font to size pixels and then let's use a monospace font like this okay better I can read them um some of them these are out of screen so the bottom left corner is now the XY I want the text to align properly and we'll do that horizontally using text line like this and vertically using text Baseline to middle and now we have something to work with let's begin to draw the first item a star now the way we're going to structure this is here at the top I will have an array of functions to draw different items it's going to be an empty array for now but I will already populate the first element with this draw Star method that we have to implement now this function is going to be written in its own file but here I want to keep references to them so that the index here matches the day where we want to draw the item makes sense now assuming that this is already implemented we can go here inside of the FI cell function and try to get the draw item function from the draw item functions at this specific index and if we succeed if this is defined then we are going to call that function with these same parameters otherwise we draw the number as before and at the moment this is not going to work because this draw Star is not defined but we will do it in its own file like so I'm going to include here a file inside of the items folder star. JS and let's close this script tag in vs code if you're going to control click this it's going to create for you the items folder and the first Javascript file inside it like so and our draw Star function given a context XY and the size let's just draw a bounding box for it at the moment so I'm going to get these top and left helper variables and then I'm going to stroke a rectangle using these values like so a square basically and there it is we're ready to draw the star now and uh I won't insist on it too much because I already Drew stars in other project like in that augmented reality Dragon Ball video but I'm going to define the radius as half this size and let's hardcode here your point count to five you could use a parameter for this but it's so common to draw five pointed stars that we're going to go with that and the way that we begin to do it is by drawing a circle using polar coordinates the circle is going to be not very round because it only has five points so essentially it becomes a regular pentagon Let's see we begin the path and we look from zero to point count like so and we need to calculate the angle now this angle is going to be I ided by Point count this gives us a percent value basically from 0 to 1 which we can use to scale 2 pi which is the full number of radians in a circle and with this angle we can move from the center of the circle towards the surface by calculating the surface x coordinate relative to X using the cosine of the angle and multiplying this by the radius because the cosine is between minus1 and 1 so we won't really see anything unless we scale it as well and the same thing for y using the sign if you're not comfortable with polar coordinates I do have a video on the topic so do check that out and now we can line to surface X surface Y and let's fill now if you save and refresh you get this regular pentagon here and the trick to make it look like a star is to double the number of points but use this one here as an outer radius and add another inner radius somewhere here so then this point is going to go here and then back up here and then back in here up here in here and so on so let's begin by typing here 10 points and renaming this to Outer radius and then inner radius I'm going to set it to half the outer radius and then here after we have the angle we still need the radius and I'm going to decide based on this parity of I so for even numbers of I will use the outer radius and otherwise the inner radius now if you save and refresh it looks like a star I kind of want it to align vertically like this like to be symmetric according to this axis here and we can do that in many ways like now it's symmetric according to this one here so if we flip here s and cosine we are going to get it symmetric to the vertical one like this and if you want this to point upwards you could for example use a minus here instead now let's add colors here as well and I think that I want to pass the color as a parameter to to the items here so maybe we go back to index HTML and let's generate a random color here I'll just randomize the Hue between 0 and 3 60 so it can be any color really and I'll just pass this Hue here like so because then the objects can use different shades of the same color somehow we'll see eventually now I'm going to pass it here like this and let's set this to fill style using this hsl syntax and now I use the Hue with the maximum saturation and 50% lightness save refresh and this is what we get every time we refresh the page the star will show in a different color now this star doesn't touch all these corners of the bounding box you can see the Gap is here that's kind of bothering me a bit but I prefer it like this otherwise scaling it vertically will not make it a regular polygon anymore so yeah it's going to be like this also the center of the star is here in the middle of the bounding box so if you would rotate it spin it around then animating it would be as expected in this way we don't need this bounding box anymore but maybe you do if you still want to play with this object so I'm commenting it out here and looks like left and top are not useful anymore so I'm going to comment them out as well to draw the ball here next to the star we're going to go to index HTML and Define a new function at index 2 let's call this draw ball and we will implement this function in its own file called ball JS now if we control click this vs code creates the file for us and as a reminder these kind of functions for drawing the object take the context the X and Y Center Point the size of the object and the Hue that controls the color as a parameter and let's test if this works by drawing this bounding box around the object so I'm getting here two helper variables that we can use to draw this rectangle a square essentially because the width and height are the same now save and refresh and this is what we get now to draw the ball I want to start off by making a ring here at the top that we can use to attach the ball on the tree and for that I will start by defining this ring object here and it's going to contain different properties like the r radius how big we want this to be and I'm going to Define it as a fraction of a size so that eventually if we want to draw these at different sizes they will scale nicely and let's just throw it at X so in the center but then the center of the Ring should be quite close to the top so maybe top plus um the radius basically if we wanted to touch the top part of this bounding box and let's define color as as well using the hsl syntax and I'm just going to use 100% for saturation and 50% for lightness and now we can draw a circle by using the arc method with a center at ring dox ring doy and now we specify the radius and we have to mention here the starting angle zero and 2 pi in radians this means 360ยฐ and we can set the stroke color to be that of the ring and stroke now if we save and refresh we get this ring up here and it's way too big I don't want it to be this size because the ball should be most of the of the screen here and the ring a very small thing at the top so let's reduce the radius maybe like this and you can see we have a problem because this is not touching the top of the screen anymore the top of the bounding box now that's because this radius value should be duplicated here as well and this code is not very good as such because I need to remember that this here stands for the radius value now you can't use here the radius value as such because this object is not yet defined but you can do a workaround and use a getter here like so we can get the value of I by returning the top plus this radius and this code is going to use this radius because we will use this getter after the object is defined so in this way we get the functionality that we want and no matter what value you set for the radius it will adapt in a way that you expect let's make this thicker so I'm going to add another parameter here for this thickness let's say like so and for it to affect we have to set here the line width to that thickness property and there it is but I don't want this ring to go outside of the bounding box you see now the outline is drawn somehow at the center of the circle that we are defining so it extends outside we could fix this by going here at this piece of code and maybe subtracting here the thickness divided by two and now this is kind of like a full circle let's make this thickness be a little bit smaller like like that and you see that this outline of this circle is now drawn on the inside this kind of functionality is really common if you look at drawing software and I'm quite sure we will need to draw a lot of circles in this project like if you remember that one video I made about drawing the Twitter logo it's all made of circles so it's really a fundamental component when making simple shapes like this and because of that maybe it's worth to invest in implementing a helper function a utility function for drawing circles easier than messing with this kind of long code all the time so how would that be well instead of this messy thing here I would like to write something like draw a circle using this context at ring dox ring doy ring. radius and now here maybe we can have some properties of the circle like the stroke style can be the ring color and then the line width can be the ring thickness and now we could specify that I want the outline to be on the inside this code is much easier to read than this one from here because first of all things like starting angle of the arc ending angle of the arc subtracting here dividing by two this kind of complex mathematics disappears from this line of code it goes inside this new function that we have to implement and every time we're going to need to do this kind of thing we don't need to re-remember the mathematics it's uh it's easier so I'm going to remove this other code from here and implement this draw object with the circle helper method and we'll do that in a separate file here I'm just going to implement it in the root folder draw. JS and control clicking this creates me the file you can see it here next to the items folder and it's going to be an object that we could extend with different methods if we want so let's say this circle as the first one given CTX XY radius and some options we have to implement it in a similar way that we had previously so first The Arc using these properties and forcing here the angles to be zero and 2 pi and then I can use object assign to CTX all of these options so if we are going to pass here options that match what the CTX is supporting then a single line of code here is going to set them to those values and now we could check to see if we want to fill this circle or not in this case the ring doesn't have a fill so it's not going to execute this piece of code but it does have a stroke so it will execute this part of code and let's just see if this works for now save refresh and you see it works but kind of like as before intersecting this part from here because the CTX doesn't understand what we mean by this inside outline here so this is a piece of functionality that we need to implement here by ourselves like if the options outline is inside I'm going to reduce the size of the radius by half this line width now save and refresh and we are now able to draw these circles with an inside outline okay let's begin to draw the ball so below this ring I'm going to define a new object to store here properties of this ball now the radius is going to be quite big let's say 45% of the size and the x value it's going to be just X so we want it centered like that and the Y value I'm going to use a getter here here as well because I want to move it from the top according to the ring radius but also this radius that needs to be accessible here and let's set the color value similarly as before and now we can reuse the draw Circle method that we implemented previously with the ball properties and we're going to pass the field style now and set that to the ball color so this is not going to have a stroke it's just going to have a fill save refresh and there it is maybe we can use a darker shade here for the ring so we can tell them apart I'm going to reduce this to 30% or maybe even darker let's say 10% yeah it's almost black but not quite black now controlling the darkness brightness of these colors could be done like this but if you think about it all these items that we are drawing it might be nice for them to share the same kind of color pattern or intensity variation and I think that we can go to draw JS and Implement here an object for managing this color so something easy like we can get the normal color by by using the Hue and outputting this as we did previously but now we can copy this few times and say maybe this is going to be the darkest value and let's say 10% I'm going to use just odd values here so dark 30% and then light 70% and the lightest 90% and with these we can go now to the ball here and say okay the color for this one should be the darkest using this Hue and now this one here should be normal using the Hue and since we have the star already this one doesn't use this kind of color management object so we could use it here as well for consistency and if we decide eventually that we want normal to mean something else all the objects are going to be affected in the same way now save refresh and things work the same as before let's play with these color values a little bit more experiment with different shades and I think that for that I want to implement the kind of radial gradient here to give this ball a highlight maybe this is going a little bit too far like um I hope you will still have ideas to make this look even nicer after I'm done with the highlights but I'm sure you'll figure out something at least I have that crazy um video where I make the ball have our reflection in it it was a really fun video and I don't think anybody answered the question of how to make it more efficient I gave there some kind of hints but um yeah check it out if you have time and want the challenge now um with this highlight I'm just moving it a little bit to the top left I'm going to implement a gradient centered at this highlight XY with zero r radius and all the way to let's just use the ball radius and see how that looks like and two color stops so the first one I'm going to try to put the light version and the last one at one or 100% let's put the darkest version and see how it looks like and we have to pass this here to the fill style we don't need this this color attribute here anymore or you could use it and set it to this gradient it's up to you now if we save and refresh we get this it's kind of dark to my taste I think I want this normal color to be somewhere here in the middle make it look brighter and more colorful somehow so let's add another color stop May be at 30% with the normal version of the H yeah this is fine but this radius here where it becomes the darkest it's too small let's try multiplying this by two yeah I think this looks nice what do you guys think we're not going to need this anymore and uh looks like we are not using this left but we are using the top so I'm commenting out just this one to draw the so next to these other items we are going to go to index HTML and here prepare another function for day3 to be draw sock we will implement this function in its own file let's call this one sockjs and in vs code if you control click this it's going to create the file inside of the items folder next to the other ones now the draw sock function is going to be with the same parameters as all other ones here for the center point the size and the Hue and I'm just going to test it by drawing the bounding box we need the top and left to pass to the rectangle drawing function like so it's going to be a square because these are the same value so save refresh and we see now here on the third day the bounding box of the item that we are about to draw now I want to draw the sock from the top here to the ankle and then towards the tip somehow so so we're going to need a y-coordinate for this ankle and I'm just going to go here and Define it let's say y plus 10% of the size and I want to draw a vertical line from the top of the bounding box to this ankle location and I could do that using drawing methods of the context directly but as we saw last time we implemented this helper function for drawing circles and lines are probably also very common things that we have to use when drawing objects so maybe we can Implement here our version of the line as well to have fewer parameters and to do more advanced things eventually maybe so how would this look like I'd say I would like to be able to draw a line on the context from the first x and y coordinate so Center to the top and then to the ankle Y and the same x value and the parameters maybe I want to specify the stroke style and let's just set it to the normal color coming from the Hue this one here and this kind of function is going to look like draw doline with the CTX from X from y 2x to Y with these options so what we do is tell the context to begin a path move to from X and Y and line two to X and Y then I'm going to use the object assign to set these past options to the context and then stroke so already some kind of save because these number of lines get reduced to just three here like so and I'm sure that in the future this is going to be much more used so it's worth the investment I think now if we save and refresh we see this vertical line appearing there and I would like to make it thick like the width of the foot basically so I'm going to go up here and Define another per variable the foot width let's say 40% of the size like so and the other parameter that I'm going to pass here is going to be the line width I'm setting it to be the foot width and when we are going to save and refresh we are actually drawing a rectangle here but without specifying so many parameters and we have a little bit of extra features here that we could use like if I'm going going to set the line cap to be round then this is going to look like so a little bit bad here because it goes outside of this bounding box but this ankle is now round and that's exactly how I want the sock to be so all we have to do is move this one by this radius down and then maybe draw on top of it u a sleeve or or something kind of uh cover up magic so let's define that radius as half the foot width so the code becomes clearer and we can move here from the top plus this radius save refresh and now we are not out of the bounding box anymore and we can do that sleeve that I mentioned so let's define a width for the sleeve and it's going to be a little bit bigger than the foot width so maybe we scale that one by 10% increasing it by 10% and now we can use the same line function again to draw from X to the top x to the top plus this radius so we just covered that kind of rounded thing at the top and then we can set the stroke style to maybe the lightest Hue and let's set the line width to the sleeve with and then the line cap I'm going to set it to not be round anymore like so and the only thing that we still need to do is this bottom of the foot here and I would really like to use a parameter to control this angle like maybe you want the sock to look like this towards the left left or to the right like a like an L shape so I would like to control that and have this object look differently if we want we can go here at the top and I'm just going to set this angle value to a default of zero so we don't need to specify it this is only if we really want and we need another variable for the food size like uh when I say foot size I mean when you buy shoes how big your foot is so that bottom part and uh this foot size we will use to scale the radius when working with polar coordinates according to this angle relative to the ankle X and Y ankle y we have it the x is just X so let's go here and figure out the tip of the foot DX is going to be X+ cosine of the angle times the foot size and the Y is going to be ankle y plus the sign of the angle times the foot size and now we can go here and draw another line like so and basically same properties as this one from here save refresh and this is what we get but this angle is something that we could control so in this case it's zero but maybe you want this to be I don't know 45ยฐ like this yeah I think this looks nice this sock reminds me of that one sorting visualizer I did with the crazy bird and uh crazy socks maybe it gives you some ideas we don't need this bounding box anymore and looks like this left variable is not used I'm commenting them out in case you want to play with them still to draw the candy cane here next to all the other items we go to index HTML and prepare a new function here in our functions array for the fourth day and let's call this one draw cane we implement this in a new file cane JS and in vs code you can control click this and it's going to create for you the file inside of this items folder here we Define our draw cane function given a context XY for the center a size and a hue to control the color I'm going to test this by quickly drawing a bounding box here I'm getting the top and left helper variables and then using this stroke wct function at the top left with the size and the size so it's going to be a square save refresh and now we see that we are ready to draw our candy cane I want this to have an arc here at the top and then continue straight down so I would like to control how wide it is and maybe how thick the the candy is so two more helper variables here the width let's say half the size and and then the thickness maybe 10% of the size like so and I'm going to use an an object to store this Arc properties and the first one is going to be the radius now I don't want this to go outside of the bounding box so I'm going to subtract here the thickness from the width and then divide by two in that way also the thickness gets halfed so it's not going to exceed the borders there now the x is just going to be X I want it to be in the middle and the Y I have to use a getter this time because from the top I want to add the radius and also half of that thickness if I don't want it to exceed the screen size and with these properties I can now begin a path and I can't use the circle method that I created previously because it's not customizable enough to draw just an arc of the circle and customizing it so much may defeat the purpose of having it called Circle there right we're basically reimplementing the arc method instead so I am using it here directly I don't think that these arcs are so common when drawing let's say but up to you if you want to experiment and Implement your own helper function now if I'm starting from PI to zero it essentially means that I'm starting it here on the left side and going all the way like this to 360ยฐ which is back to zero in the same way that the clock starts again and again now if we save and refresh we see that this looks like this and it's not intersecting this bounding box so similar things that we have done already before for the ring here and I also want to do a line to the bottom so line to the same Arc X plus the radius to the bottom because I want it to continue from here all the way here and this bottom is not yet defined we can add it here at the top because it means the bottom of this region where we are allowed to draw fits well next to these other helper variables now if we save refresh we get this General shape that we want and I just want to decorate it by having those kind of Stripes over it for that I'm going to basically draw the same path again so stroke it one more time and uh let's try to set a Different Stroke style maybe a dark one and the dash so the line Dash I will try to reuse the thickness value that we have defined here at the top because sometimes reusing these values if it looks good then there's no point defining another variable and thinking of another name for it and I think it's going to work because it will lead to a balanced result like the thickness between the stripes same as the thickness of the cane itself so I think it's a good choice and then let's stroke one more time like this and this is what we get maybe the contrast here should be bigger I don't know it depends also about the Hue how big the contrast is going to be like here it's not that visible so you can play with these if you want maybe lightest could be here and then normal for this one if you want a brighter object yeah maybe something like this is nice all these dashes remind me of that one project I made with the train that train simulation and the troll problem project that game it was main only using these line dashes pretty much check it out if curious and um try to make this one better I'm sure you can do that as well to draw the fifth item here here next to the other ones we're going to go to index HTML and prepare another function here for the fifth day draw bow and we'll implement this function in its own file BJs in vs code if you control click this it's going to create the file inside of this items folder and our draw bow function given CTX X and Y for the center location a size and a hue to control the color I'm going to test it first by drawing this bounding box these two helper variables let me draw this Square here which we'll use for reference so that we make sure that our item fits in the space that we want now I'm going to begin a path starting at the center and draw this kind of shape all the way to the corners that kind of looks like a bow and then we'll fine-tune that to make it look a bit nicer so let's begin a path and set the fill style to our normal color given the Hue move to the center point and now line to the left Top Line to left bottom we don't have this one yet up here but we'll have to Define that as well as the right variable and the final to the right top and let's fill this shape now up here we need that right to be X+ size by 2 and the bottom y + half the size save refresh and it kind of looks like a bow already but a very spiky one so to make it curve I'm going to replace all these line twos with a curve two and this is not going to be the destination anymore it's going to be the control point the destination is going to be here so the control point is going to kind of pull on it and then it's going to go here then this will be the new control Point going here and so on we'll use a quadratic curve to function call here you can also play with bezier curves if you want more control here but basically I want to go to left and Y being controlled by this one point if I save and refresh you see how this one is being pulled up in that direction and this point that you see here is actually halfway from here to this Middle Point on this segment so kind of good to know that because it means that the height of this bow is going to be half of the width of this Bow by the end let's do the rest so here going to X and Y through left and bottom and um this one we don't need it anymore because we are already at X and Y so these two just need to be modified symmetrically on the right side and the last okay good I also want to have a kind of knot here appearing in the middle this just looks like the I don't know infinity symbol so I'm going to go here and let's store these not properties inside of its own object like so the size maybe 30% of everything and then for the top and the bottom I'm going to draw this as a rectangle maybe a rounded Corner rectangle let's see so I need the top and the left in the same way that we needed top and left here for this uh bounding box and top I want to be able to use the size that we just calculated so I'm using a getter and I return y minus this size / 2 and for the left xus this size / by and let's use a roundness so that we draw this kind of round rectangle for that we begin a path set the FI style maybe to a darker color and round rectangle left top with height is the size let's just use a square and then this roundness at the end and fill save refresh and that's the bow this red one reminds me of the one lard is wearing let me know if you want me to make more videos like that maybe this not could be a little bit smaller let's try here maybe 25 yeah but now it kind of looks almost like a circle so let's also decrease this round this by half okay this looks good to me and what do you guys think I'm going to comment this out and let you explore to draw the Bell on day six we're going to go to index HTML and add a new function here at the sixth index draw bell and this will be implemented in its own file BJs control clicking this on vs code is going to create it for us in the items folder and let's Implement quick version of it that just displays the bounding box I take out these helper variables top and left and draw a rectangle from this location using the sizes the width and the height save refresh and now we have our placeholder here and it gives us a good reference when drawing the item now I want the Bell to hang on something a ring like what we did here for the for the ball so let's just copy that code from there basically this I'm going to take it to the Bell save refresh and we have the ring to start with and now the Bell also has that kind of that Clapper at the bottom that ball there I want to draw that now because after that we can worry about this Bell shape it's going to be on top of that ball that we see at the bottom so let's define an object for this Clapper and it's going to have a radius maybe same as that of the ring at the top and the x is going to be just X so we Center it and then the Y value I'm going to need to use a getter because I'm going to subtract from the bottom this radius that we just defined up here remember that this radius is not accessible before this object is created so basically we need to use a getter for it and bottom should be added here to our helper variables because it relates to the bounding box now we can continue here and give this Clapper color as well maybe a dark color because it's going to be shadowed by the Bell itself and then here I'm going to use our draw Circle method at X and Y using the clappers radius and the field style is going to be set to the clappers color now save refresh and this is what we get for the Bell I'm going to start probably here at the bottom of this ring let's see the whole ring this time and draw a triangle to begin with like so so it cuts this Clapper in half let's define our Bell object the top is going to be top plus this ring radius time 2 so we want to see the whole ring this time and then the bottom is going to be bottom minus The Clapper radius so it cuts it in half and let's begin a path and draw this kind of triangle we're going to fill it let's give it a normal color from this Hue so normal intensity and then move to the top of the bell and then line to the left of the screen using the bell bottom and line to the right of the screen and the bell button fill and remember to Define this right because it's also missing here from our helper variables X plus half the size save refresh and uh kind of looks like a bell already but um bells are round you should use some kind of curve here and this is going to show you how to use the bezier curve which has two control points and what we do on this side should be somehow mirrored on the right side as well so I'm going to add to this Bell object this offset and um this control Point offset is going to somehow specify how far we want in both directions to control the bzier curve the one that has two control points so let's say not really half the size but let's say 25% of the size because that's going to move from here a quarter of the size here so our control points are going to be somewhere here maybe we put one here at the top and one here at the bottom and that's going to give us that kind of snake like shape we'll see so we change now the first line two to be a bizer curve two and the control points so x minus this Bell off set at the top the second one the same thing but we are going to use the bell bottom and then the destination is going to be left and bottom same that we had previously in the line to now save refresh and you can see what we have here you can play with these control point x offsets the way you want like if you're going to make it all the way here here um like so you're going to get this kind of bell that doesn't have that s- like shape because both of them are are here but then controlling this more or less is going to give you a different kind of shape so maybe you want less of this here and more here like like I'm doing now and then when you're happy with this repeat the same on the right side we still need to have the line to the right and the bell bottom because it's this straight line here here and then make our way back up here by somehow reversing those those values so another Bia curve 2 this time we will add these offsets and we have to remember that we are starting at the bottom so we use the bottom first and then the same with the top and we end this time we end at the middle here so that's X and the bell top and there it is that reminds me I haven't said click the Bell but in a very long time I don't like saying that to draw the snowball here on day seven we're going to go to index HTML and add another function here here to our array at the seventh Index this is going to be draw snowball and we'll implement it in a new Javascript file snowball JS control clicking this is going to create the file in vs code inside of this items folder snowball JS next to all the other ones and let's write a quick function for drawing the snowball with the context at the XY size and Q and uh we'll begin with the bounding box I'm getting these top and left helper variables to draw the rectangle which is a square I'm just reusing the size both for the width and height save refresh and now this shows the bounding box here that we can use as a reference when making the snowball and the snowball is a circle basically at least that's what we'll use as a starting point so let's try to draw that but we'll draw it by making many small segments that kind of look like a circle but then we'll have control over each of them to make it look a little bit more um noisy so the radius is going to be half the size and then let's begin a path where we VAR the angle let's say a from zero all the way to 2 pi radians and we increase by a very small value and I like to use fractions of Pi here so increasing by a small value like this means that we will pretty much draw a very nice looking Circle here we need to get the coordinates on top of the circle relative to this Center Point X and Y so the point on the surface of the circle X is going to be X+ and now we can scale the cosine of the angle and then for the Y we do the same relative to Y with the sign of the angle if you want to learn more about these polar coordinates I do have a video on the topic and then we line to surface X surface y like so and let's set a f color before actually filling it like so I'm using the lightest color from our color generator here save and refresh and we get the circle done now I still want to make it look a little bit better so to make it look like a little bit noisy edge here I'm going to Define first a Max radius so this is going to be the same value that we used for the radius previously but here I'm going to control the size of the radius relative to this Max radius multiplied by one which is like 100% minus a very small random value like random times 0.1 this math. random gives you a value between 0 and 1 so now it's going to give you a value between 0 and 0.1 and we subtract that from 100% of the max radius so if we save refresh we can see this kind of shape appearing here and it's okay but sometimes I think that this effect is too much so let's uh decrease this by half so 0.05 maybe yeah this is much better what I want to do next is kind of give it the shadow at the bottom and the way we'll do that is by drawing this one again on top of it but darker in the back and lighter in the front so doing things again typically shouts out take something out as a function and we'll do just that so all this code here for drawing the noisy ball it's going to be a function called draw noisy ball with all these parameters like so and the given color this color will be the parameter that we change so let me align this like so and replace this lightest Hue here with this color and now we can call this draw noisy ball with the same parameters as before and let's say we start with the normal color which is darker now save and when I refresh you can see it works pretty much as before but now the color is darker as previously and we could call this two times so copy this like so and let's draw on top top here with the lightest color that we have and to see it affecting somehow I'm just going to have the radius for now and this is what we get it's kind of like a very round avocado sliced in a way that I never slice an avocado okay but the point is not to draw this uh smaller I'm going to use the same size really but Define an offset so I'm going to draw this not in the center anymore I'm going to offset a little bit to the left and a little bit towards the top so here instead of X and Y I'm going to multi-edit this offset do X and Y saving and refreshing is going to look like this you kind of see the shadow appearing here um but of course I don't want this to go outside of everything and one way to limit this is to tell the context that we just want to draw over what already exists on the canvas and we can do that by setting here the global composite operation to Source a top and when we do that it only draws on top of what is there already and you can see here this um is drawing over this bounding box but that's something we don't really care about because we don't need it really or these things so this looks just fine and uh maybe I want this Shadow to be a little bit smaller and more towards the bottom like um I could set here yeah like that so sun is coming from the top basically and I think that this looks really nice when you have some kind of bluish color there for the snow maybe like this right now one thing that I always like to do when I set values like these less used properties like the global composite operation I tend to like to reset them so the default value is this um s Source over and it's not going to change anything here but future drawing of this object is going to not cause big problems and of course you could save the canvas State before drawing all of these and resetting it at the end that's also a very common practice to avoid any unwanted effects but um up to you which approach is more suitable in your case all this snow reminds me of that video Master skier made about teamwork to draw the candle here on number eight we're going to go to index HTML and uh set up a function at the eighth index in our array let's say draw candle and we'll implement this in a separate file candle JS control clicking this in vs code is going to create it for us in the items folder like so and we can implement the function given CTX DX and Y Center Point size and the Hue for controlling the color now I'm going to take a reference to the top and left values so I can Define the top left corner when drawing a bounding box here it's going to be a square with the same width and height in this way we will see here where we want our candle to fit and to draw the candle I'm going to basically break it up in two portions the candle stick and the FL flame so let's have an object here for the stick now the width of the stick let's say 30% of the size and the height may be 70% of the size so then the flame is on the top 30% and the X we'll just keep it to Center and the bottom we want a helper variable for this as well similarly to how we have the top but adding half the size now the top part of the stick is going to depend on the height starting at the bottom so to be able to reference height we are going to implement the getter here for the top returning this bottom minus this height and we'll set the color to let's just say the normal Hue for now now drawing this stick I'm going to use that line trick I'm going to make a line like so from the top to the bottom of the stick and we'll set the stroke style to the color and then the line width is going to be the width of the stick save refresh and you're going to get this and now for the flame I'm going to draw an ellipse and we will use ellipses to somehow make this candles stick also look like a cylinder so maybe it's worth extracting ellipse as a kind of a helper function in the same way that we did for the line here previously when we drew the the sock I think so let's keep that in mind when we implement the flame here so the flame it's going to have a width maybe the stick width 30% of that so maybe it's nice to have this value relative to the to the width of the stick then the result looks more balanced and then the height is going to be the full size minus the stick height in that way we have control so it always fits in that bounding box the center is going to be X and then for the ellipse we're going to need two radi the X radius and the Y radius I'm going to use here Getters for this because I want the width and height of this flame object to control what the radi are going to be like so so now I'm referencing them using this otherwise it wouldn't work and then let's have a y value for this flame as well and that's going to be the top of the stick minus the this y radius which we have at the moment so like this and a color I'm just going to set this to Yellow I'm not using this um color object for this one because I think fire is usually yellow in these and I don't want the candle to have a weird flame so maybe hardcoded value is just fine for this item and now the ellipse object what I would like it to be able to do is draw an ellipse at the context using the context at the flame X Y using the flame X radius and Y radius and now maybe some options like the field style let's set it to the flame color like this and we don't have this function implemented yet but we can do it in the draw object maybe below the circle here since ellipses and circles are related to each other so parameters will be a little bit different because it has two radii here and then the options are essentially for setting the Style We Begin The Path and now the ellipse method of the context has quite many parameters so it's one of the reasons why I wanted to extract this in our own uh function XY X radius and Y radius are clear but then the next one is the rotation maybe we want rotation at some point so we might extend this function to support that as well but then it's the start angle and then it's the end angle so extracting this into our own function simplifies all of this logic there we we maybe don't want to draw half an ellipse so many times and very often when we want to draw the full ellipse we don't have to remember what those are when we use this new function here and these options I'm just going to copy the way that we assign them from the circle object so like this and now we save refresh and there's the flame it already looks kind of nice but I really want want to reuse the ellipse object to make this kind of look like a cylinder so the stick itself needs radi for those ellipses and um we need to modify also this bottom so it doesn't go all the way here so that the ellipse doesn't cross this one so it will move up by the Y radius of of this one let's see back to the candle to the stick I'm going to go here and say a x radius this is going to have to be half the width and for the Y radius I guess it defends on the viewing angle I'm just going to set it to half the X radius like this and now we need to remember this bottom has to move up by y radius as well so here we can set this one using a getter like this so we have access to this y radius and I think we need to do the same thing for the top let's see yeah because it this flame now intersects over there so for the top we also need to add here this y radius good and now we're ready to draw those so I'm going to go below this draw line and draw an ellipse at the stick X bottom with the stick X radius and Y radius and then a f style of the stick color save refresh and this is our bottom part here and the same for the top part so I'm going to just copy this like so with top instead of bottom here like that and I want to make this look like a light color here because this shade should be brighter because of the flame so I'm going to Define here for the Candlestick another color a light color the lightest that we have our flame is very bright and then let's use this one for the top one here all right very nice maybe this can be a darker version of the color so that the yeah the contrast is bigger this reminds me of those uh can

Original Description

Learn how to create a Christmas calendar with JavaScript and HTML canvas. You will create 25 different "Christmasy" icons. You will learn about coordinates, basic math, and programming techniques. This course is a great way to dive into modularity, reusability, and writing consistent code. You can even submit your own versions for Radu to showcase at the end of this year. โœ๏ธ Course created by @Radu . ๐Ÿ’ป Code: https://github.com/gniziemazity/christmas_calendar ๐Ÿ’ฌ Radu's discord to submit your creations: discord.gg/gJFcF5XVn9 โค๏ธ Try interactive JavaScript courses we love, right in your browser: https://scrimba.com/freeCodeCamp-JavaScript (Made possible by a grant from our friends at Scrimba) ๐ŸŽ‰ Thanks to our Champion and Sponsor supporters: ๐Ÿ‘พ Drake Milly ๐Ÿ‘พ Ulises Moralez ๐Ÿ‘พ Goddard Tan ๐Ÿ‘พ David MG ๐Ÿ‘พ Matthew Springman ๐Ÿ‘พ Claudio ๐Ÿ‘พ Oscar R. ๐Ÿ‘พ jedi-or-sith ๐Ÿ‘พ Nattira Maneerat ๐Ÿ‘พ Justin Hual -- Learn to code for free and get a developer job: https://www.freecodecamp.org Read hundreds of articles on programming: https://freecodecamp.org/news
Watch on YouTube โ†— (saves to browser)
Sign in to unlock AI tutor explanation ยท โšก30

Playlist

Uploads from freeCodeCamp.org ยท freeCodeCamp.org ยท 0 of 60

โ† Previous Next โ†’
1 React: Production Server Setup Part 2 - Live Coding with Jesse
React: Production Server Setup Part 2 - Live Coding with Jesse
freeCodeCamp.org
2 cookies vs localStorage vs sessionStorage - Beau teaches JavaScript
cookies vs localStorage vs sessionStorage - Beau teaches JavaScript
freeCodeCamp.org
3 Browser history tutorial - Beau teaches JavaScript
Browser history tutorial - Beau teaches JavaScript
freeCodeCamp.org
4 Graph Data Structure Intro (inc. adjacency list, adjacency matrix, incidence matrix)
Graph Data Structure Intro (inc. adjacency list, adjacency matrix, incidence matrix)
freeCodeCamp.org
5 React: Parameterized Routing with Next.js - Live Coding with Jesse
React: Parameterized Routing with Next.js - Live Coding with Jesse
freeCodeCamp.org
6 React: Dealing with jQuery Issues - Live Coding with Jesse
React: Dealing with jQuery Issues - Live Coding with Jesse
freeCodeCamp.org
7 setInterval and setTimeout: timing events - Beau teaches JavaScript
setInterval and setTimeout: timing events - Beau teaches JavaScript
freeCodeCamp.org
8 Browser and Device Testing - Live Coding with Jesse
Browser and Device Testing - Live Coding with Jesse
freeCodeCamp.org
9 Last Minute Updates - Live Coding with Jesse
Last Minute Updates - Live Coding with Jesse
freeCodeCamp.org
10 Post Launch Updates - Live Coding with Jesse
Post Launch Updates - Live Coding with Jesse
freeCodeCamp.org
11 React: Setting Up Google Analytics - Live Coding with Jesse
React: Setting Up Google Analytics - Live Coding with Jesse
freeCodeCamp.org
12 React: Masonry Layout - Live Coding with Jesse
React: Masonry Layout - Live Coding with Jesse
freeCodeCamp.org
13 Load Balancing Digital Ocean Droplets - Live Coding with Jesse
Load Balancing Digital Ocean Droplets - Live Coding with Jesse
freeCodeCamp.org
14 try, catch, finally, throw - error handling in JavaScript
try, catch, finally, throw - error handling in JavaScript
freeCodeCamp.org
15 Load Balancing: SSL Passthrough Setup - Live Coding with Jesse
Load Balancing: SSL Passthrough Setup - Live Coding with Jesse
freeCodeCamp.org
16 Graphs: breadth-first search - Beau teaches JavaScript
Graphs: breadth-first search - Beau teaches JavaScript
freeCodeCamp.org
17 React: Masonry Layout Part 2 - Live Coding with Jesse
React: Masonry Layout Part 2 - Live Coding with Jesse
freeCodeCamp.org
18 React: WordPress API Live Search - Live Coding with Jesse
React: WordPress API Live Search - Live Coding with Jesse
freeCodeCamp.org
19 Creating WordPress Custom Post Types - Live Coding With Jesse
Creating WordPress Custom Post Types - Live Coding With Jesse
freeCodeCamp.org
20 Dates - Beau teaches JavaScript
Dates - Beau teaches JavaScript
freeCodeCamp.org
21 Miscellaneous Front End Updates - Live Coding with Jesse
Miscellaneous Front End Updates - Live Coding with Jesse
freeCodeCamp.org
22 Merging a Pull Request from GitHub - Live Coding with Jesse
Merging a Pull Request from GitHub - Live Coding with Jesse
freeCodeCamp.org
23 React + Prettier + Standard JS - Live Coding with Jesse
React + Prettier + Standard JS - Live Coding with Jesse
freeCodeCamp.org
24 React: Sortable Responsive Table - Live Coding with Jesse
React: Sortable Responsive Table - Live Coding with Jesse
freeCodeCamp.org
25 Geolocation Sorting by Distance - Live Coding with Jesse
Geolocation Sorting by Distance - Live Coding with Jesse
freeCodeCamp.org
26 Tradeoff Matrix - Agile Software Development
Tradeoff Matrix - Agile Software Development
freeCodeCamp.org
27 The Definition of Ready - Agile Software Development
The Definition of Ready - Agile Software Development
freeCodeCamp.org
28 Getting first React job without experience - Ask Preethi
Getting first React job without experience - Ask Preethi
freeCodeCamp.org
29 React: Google Analytics Click Tracking - Live Coding with Jesse
React: Google Analytics Click Tracking - Live Coding with Jesse
freeCodeCamp.org
30 Submitting a PR to an Open Source Project - Live Coding with Jesse
Submitting a PR to an Open Source Project - Live Coding with Jesse
freeCodeCamp.org
31 Should I go back to school to get CS degree? - Ask Preethi
Should I go back to school to get CS degree? - Ask Preethi
freeCodeCamp.org
32 Hero Section CSS Changes - Live Coding with Jesse
Hero Section CSS Changes - Live Coding with Jesse
freeCodeCamp.org
33 Working Agreement - Agile Software Development
Working Agreement - Agile Software Development
freeCodeCamp.org
34 A day at Pennybox with Co-Founder Reji Eapen
A day at Pennybox with Co-Founder Reji Eapen
freeCodeCamp.org
35 React: Sorting and Filtering Data - Live Coding with Jesse
React: Sorting and Filtering Data - Live Coding with Jesse
freeCodeCamp.org
36 React: Sorting and Filtering Data Part 2 - Live Coding with Jesse
React: Sorting and Filtering Data Part 2 - Live Coding with Jesse
freeCodeCamp.org
37 React: Building a New UI - Live Coding with Jesse
React: Building a New UI - Live Coding with Jesse
freeCodeCamp.org
38 Definition of Done - Agile Software Development
Definition of Done - Agile Software Development
freeCodeCamp.org
39 Getting started with jQuery (tutorial) - Beau teaches JavaScript
Getting started with jQuery (tutorial) - Beau teaches JavaScript
freeCodeCamp.org
40 Making a React Blog with WordPress Content - Live Coding with Jesse
Making a React Blog with WordPress Content - Live Coding with Jesse
freeCodeCamp.org
41 React, NextJS, CSS - Live Coding with Jesse
React, NextJS, CSS - Live Coding with Jesse
freeCodeCamp.org
42 jQuery events - Beau teaches JavaScript
jQuery events - Beau teaches JavaScript
freeCodeCamp.org
43 React/NextJS Routing and WordPress API Custom Types - Live Coding with Jesse
React/NextJS Routing and WordPress API Custom Types - Live Coding with Jesse
freeCodeCamp.org
44 React: Working with API Data - Live Coding with Jesse
React: Working with API Data - Live Coding with Jesse
freeCodeCamp.org
45 React: Refactoring Components - Live Streaming with Jesse
React: Refactoring Components - Live Streaming with Jesse
freeCodeCamp.org
46 jQuery effects - Beau teaches JavaScript
jQuery effects - Beau teaches JavaScript
freeCodeCamp.org
47 More React Refactoring - Live Coding with Jesse
More React Refactoring - Live Coding with Jesse
freeCodeCamp.org
48 animate in jQuery - Beau teaches JavaScript
animate in jQuery - Beau teaches JavaScript
freeCodeCamp.org
49 "Finishing" My React Site - Live Coding with Jesse
"Finishing" My React Site - Live Coding with Jesse
freeCodeCamp.org
50 Starting a New React Project (P2D1) - Live Coding with Jesse
Starting a New React Project (P2D1) - Live Coding with Jesse
freeCodeCamp.org
51 React Project 2 Day 2: Learning Material UI - Live Coding with Jesse
React Project 2 Day 2: Learning Material UI - Live Coding with Jesse
freeCodeCamp.org
52 The Agile Manifesto - Agile Software Development
The Agile Manifesto - Agile Software Development
freeCodeCamp.org
53 jQuery: get and set with http, text, val, and attr - Beau teaches JavaScript
jQuery: get and set with http, text, val, and attr - Beau teaches JavaScript
freeCodeCamp.org
54 React Project 2 Day 3 - Live Coding with Jesse
React Project 2 Day 3 - Live Coding with Jesse
freeCodeCamp.org
55 The INVEST approach to product backlog items
The INVEST approach to product backlog items
freeCodeCamp.org
56 React Project 2 Day 4 - Live Coding with Jesse
React Project 2 Day 4 - Live Coding with Jesse
freeCodeCamp.org
57 Chickens and Pigs - Agile Software Development
Chickens and Pigs - Agile Software Development
freeCodeCamp.org
58 React Project 2 Day 5 - Live Coding with Jesse
React Project 2 Day 5 - Live Coding with Jesse
freeCodeCamp.org
59 jQuery: add and remove DOM elements - Beau teaches JavaScript
jQuery: add and remove DOM elements - Beau teaches JavaScript
freeCodeCamp.org
60 React Project 2 Day 6 - Live Coding with Jesse
React Project 2 Day 6 - Live Coding with Jesse
freeCodeCamp.org

Learn to create a Christmas calendar using JavaScript and HTML canvas, covering coordinates, basic math, and programming techniques. This project is a great way to dive into modularity, reusability, and writing consistent code. By following this tutorial, you will create 25 different Christmasy icons and learn valuable skills in JavaScript programming.

Key Takeaways
  1. Set up the HTML canvas for rendering the Christmas calendar
  2. Create a JavaScript function to generate the calendar layout
  3. Use coordinates and basic math to position the icons
  4. Apply programming techniques for modularity and reusability
  5. Style the calendar with CSS
๐Ÿ’ก Using JavaScript and HTML canvas, you can create interactive and dynamic graphics like a Christmas calendar, applying programming techniques for modularity and reusability.
๐Ÿ”’ Pro feature: Ask AI to explain this lesson โ†’

Related Reads

Up next
How to Speed Up Your WordPress Website with WP Rocket โšกTutorial 2026
Matt Tutorials
Watch โ†’