Etch-A-Sketch
5 minutes 10 seconds average read (1032 words)So in my learning of JavaScript, with Wes Bos, I've now created an Etch-a-Sketch. Use the arrow keys and have a go. Below I'll explain how it works, this is another way of learning. By explaining something means that you truly understand how it works.
HTML
<div class="canvaswrap"> <canvas width="1600" height="1000" id="etch-a-sketch"></canvas> <div> <button>Shake!</button> </div> </div>
This is simple really, a <canvas>
to draw upon and a <button>
to reset the canvas.
JavaScript
Setting up the Variables
const canvas = document.querySelector(`#etch-a-sketch`); const shake = document.querySelector(`.shake`); const ctx = canvas.getContext(`2d`); const MOVE_AMOUNT = 5; const { width, height } = canvas; let x = Math.floor(Math.random() * width); let y = Math.floor(Math.random() * height); let hue = 0;
canvas
This creates a variable called canvas from the id="etch-a-sketch"
which is set on the <canvas>
element
shake
This creates a variable called from the class="shake"
which is set on the <button>
element
ctx
This sets the context of the canvas to 2d
MOVE_AMOUNT
This sets a variable for how far the dot will move and how big the dot will be
width, height
These are destructured variables taken directly from the canvas, you can find out move about destructuring assignments at javascript.info.
x, y
Here I am setting x and y to be a random point on the canvas based upon its width & height.
hue
This is setting a starting value for the colour of the dot, this will be then used in a hsl colour setting later on.
Setting up the canvas for drawing on
ctx.lineJoin = `round`; ctx.lineCap = `round`; ctx.lineWidth = MOVE_AMOUNT; ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`; ctx.beginPath(); ctx.moveTo(x, y); ctx.lineTo(x, y); ctx.stroke();
Here we are setting up the default settings to start drawing on the <canvas>
.
lineJoin & lineCap
These 2 settings tell the line how to join to other lines and how the end of the line will look.
There are 3 options for lineJoin
:
round
bevel
mitre
There are 3 options for lineCap
:
butt
round
square
lineWidth
This sets how wide the line will be that's drawn on the <canvas>
.
strokeStyle
This is used to set how the stroke will look.
There are 3 options for strokeStyle
:
color
gradient
pattern
In my example, I'm setting the colour to be an hsl value with the hue variable, saturation 100% and lightness 50% - hsl(${hue}, 100%, 50%)
.
beginPath()
This simply starts a new path on the <canvas>
.
moveTo()
This sets the start point of a new path/stroke on the <canvas>
.
lineTo()
<canvas>
.stroke()
This will draw the stroke between moveTo()
and lineTo()
on the <canvas>
.
Listening to the Arrow Key events
const handleKey = event => { if (event.key.includes('Arrow')) { event.preventDefault(); draw({ key: event.key }); } };
This is an arrow functions called handleKey
which has a parameter called event
. This allows use the say, for every event that happens do these things…
In this case it means:
- if the event is:
- a key event
- which has in it the press of an Arrow key
- then stop scrolling by default
event.preventDefault();
- then call the draw function, which we'll talk about soon
Drawing stuff on the <canvas>
So at this point after creating all these functions and variable I actually need to draw something on then <canvas>
.
const draw = ({key}) => { hue += MOVE_AMOUNT; ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`; ctx.beginPath(); if (x > width) {x = width;} if (x < 0) {x = 0;} if (y > height) {y = height;} if (y < 0) {y = 0;} ctx.moveTo(x, y); switch (key) { case 'ArrowUp': y -= MOVE_AMOUNT; break; case 'ArrowDown': y += MOVE_AMOUNT; break; case 'ArrowLeft': x -= MOVE_AMOUNT; break; case 'ArrowRight': x += MOVE_AMOUNT; break; default: break; } ctx.lineTo(x, y); ctx.stroke(); };
So this is relatively simple I'm setting the variables created earlier.
- Set the colour + MOVE_AMOUNT
- If x is greater the width set x to be width of the canvas
- if x is less then 0 set x to 0
- If x is greater the width set y to be height of the canvas
- if x is less then 0 set y to 0
- then listen to the arrow keys:
- if key = ArrowUp make x = x - MOVE_AMOUNT
- if key = ArrowDown make x = x + MOVE_AMOUNT
- if key = ArrowUp make x = x + MOVE_AMOUNT
- if key = ArrowDown make x = x - MOVE_AMOUNT
- Then draw the stroke
Clear the Canvas when Finished
const clearCanvas = () => { canvas.classList.add('shake'); ctx.clearRect(0, 0, width, height); canvas.addEventListener('animationend', function(){ canvas.classList.remove('shake') }, {once: true} );}
This function says when the <button class="shake">Shake</button>
, is clicked then clear the <canvas>
.