Last week in our festive coding challenge, we explored how to code a sliding puzzle toy with some of the latest front-end techniques to grace the developer’s tool kit. But with Christmas drawing ever nearer, we thought it was time to up the ante with a ‘build your own emoji tree’ creation from front-end developer Kate. You can have a play below (or on CodePen). But do tweet us with your tree designs, @simpleweb, we’d love to see them!
If you want to build one yourself, stick around for our second festive tutorial from Kate below.
Here is the seasonal story of how the tree came to be:
The Original Tree🌲
First of all, I created a basic tree in Sketch, exported it as an SVG and used the code from that. As you can see it’s comprised of four overlapping, mathematically beautiful right-angled triangles (
polygons), and a
rect for the trunk. Later, I added a few shadows to each triangle to make it look marginally more realistic, so this code did get a bit more complex.
Tree Topper Selector ⭐
I started off the customisation by controlling something simple – the decoration to sit at the top of the tree. Traditionally, this is either a star or an angel, although the Apple angel emoji is a quite creepy baby with wings but no body, so that’s why a star is the default. When a different option is selected, the
handleChange function sets that as the
textContent of the
topSelector div. Easy!
Add Present 🎁
In a similar vein, I added an event listener to a button labelled “Add present”, which adds a present emoji to the
textContent of the present container (making sure to set its width to match that of the tree, or it all ends up a mess).
Time to make things a bit more interesting. I went back to Sketch to add baubles on each branch, then set about letting the user change their colour. This was done with custom CSS properties, which are set on the root element with the prefix
…referenced in the fill attribute for each bauble using the
…and controlled via the values of a couple of colour pickers with ‘change’ event listeners.
Once it was 3D the tree called out for more decorations. I added a ‘click’ event listener to the tree itself that adds a div to the DOM, setting its top and left values according to the coordinates of the MouseEvent (
textContent is set to the value of a
select element, filled with an increasingly wide variety of emojis that vaguely resemble Christmas ornaments.
Being absolutely positioned, the decorations didn’t really work when the browser got resized. I sneakily solved this problem by moving the tree into the top left, after an embarrassingly long time trying to add new SVG text elements to the tree instead.
When I came to add lights (i.e. yellow
circle s) I worked out the trick behind this, which wasn’t all that difficult:
const light = document.createElementNS("http://www.w3.org/2000/svg", 'circle'); rather than
const light = document.createElement('circle');
Next, I wanted to make the lights twinkly. This was done with a function that changes the radius of each one every 500 milliseconds, selecting a random number of pixels between 1 and 2.
Let it snow ☃️
letItSnow(), which includes two nested functions,
createFlake() creates an absolutely positioned
<div> which starts off with its
top property set to 0px, and
left set to a random number within the width of the screen.
snowfall() increases the
top value by 1px at a random interval, so each one falls down the screen at its own speed.
This was lovely but as the flakes kept falling forever it made my laptop whir quite a lot, so I made each flake remove itself from the DOM when its top exceeded the height of the tree. This led to a few simple styling changes to add some snowy ground (a white div with a width of 100%), and a limit on the number of presents in the present container, so they wouldn’t look silly with snow disappearing halfway down them.
As the processing power usage still sounded excessive I set about making it possible to stop new snow being created. Originally this was with the same button, which toggled its
textContent from “Let it snow! ❄️” to “Stop, it’s too snowy 🌨️” when clicked, and used this
textContent value to determine what function to perform. This all got horribly confusing and led me to look into various solutions, such as a simple
return; to exit the
letItSnow() function, and custom errors with a throw statement.
None of this worked, and what I had missed was that the two buttons have to do two separate, but quite simple, things –
letItSnow() (set an interval on
stopSnow() (clear that interval). This was also much easier once they were actually two different buttons (which each toggle the other to
display: none;, so they appear to be the same button). Crucially, they do both need to refer to
snowing, the value returned by setting the interval, so I had to set
snowing = null in global scope.
Cat Button 🐈
At the request of a colleague I added a cat into the mix, which knocks decorations off. The suggestion was actually to throw a cat into the tree, but I thought that was a bit too ambitious and cruel.
To make tinsel I used SVG
path elements, created by
mouseup events set on the tree while tinsel is selected in the decoration selector. The
d attribute for each of them is set to four coordinates: M (the start of the tinsel) has the coordinates of the mousedown event (with some maths to account for margins), and C (Bezier curve) has the coordinates of a spot 18px below the start point, followed by 18px below the end point, then the end point itself, which is where the mouseup event occurred.
The two lower points make the path curve downwards slightly. A better explanation can be found here.
It could look a bit more like tinsel, and also doesn’t really work if someone tries to break it by swiping vertically rather than straight across the tree, but it was quite interesting to work out.
If you’d like to discuss your startup or project, get in touch with Simpleweb today.