CodeNewbie Community 🌱

Cover image for Commit21 //#JavaScript30 - Day 8 [HTML5 Canvas]
Janet Webster
Janet Webster

Posted on

Commit21 //#JavaScript30 - Day 8 [HTML5 Canvas]

Photo of HTML5 Canvas


I am learning with Skillcrush. Please check them out and consider signing up if you're looking to break into tech! Receive $250 off your course by using the link above. Use the coupon code: TWIXMIXY
NOTE: this discount is for Break Into Tech + Get Hired package exclusively. It's the same program I am participating in!


Today's challenge comes from JavaScript30.

Sheesh. Woke up with another headache today! Thankfully it seems to have dissipated at this point. I even took a COVID test to make sure I wasn't sick. It may be all the rain coming through, causing sinus pressure or something.

This challenge looks like a lot of fun, so let's jump into it!

JavaScript30 - Day 8

So this is blowing my mind a bit. There is no CSS from what I can tell, except for a zero'd out margin for the html, body.

HTML5 starter code

So everything we are creating today is going to be done through JavaScript built upon the latest HTML5 canvas.

So what is HTML5 Canvas?

The HTML element is used to draw graphics, on the fly, via JavaScript.
The element is only a container for graphics. You must use JavaScript to actually draw the graphics.
Canvas has several methods for drawing paths, boxes, circles, text, and adding images.

To start us off, we are given a snippet of code in the starter HTML.

<canvas id="draw" width="800" height="800"></canvas>
Enter fullscreen mode Exit fullscreen mode

So our first step is to connect our javascript to the canvas through the id draw.

const canvas = document.querySelector('#draw');
Enter fullscreen mode Exit fullscreen mode

Next we want to get the context.
Canvas Rendering Context 2D
In this example we are doing 2D. The instructor discusses the ability for 3D for things like video games.

const ctx = canvas.getContext('2d');
Enter fullscreen mode Exit fullscreen mode

This statement will establish our context.

Next we want to size the canvas to fit the window, so it isn't restrained to the initial width/height settings.

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
Enter fullscreen mode Exit fullscreen mode

Then we want to establish some of the base settings.
Information on lineCap, lineJoin, and strokeStyle.

ctx.strokeStyle = '#BADA55';
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
Enter fullscreen mode Exit fullscreen mode

"Badass" color is a pastel green.

#BADA55

let isDrawing = false;
Enter fullscreen mode Exit fullscreen mode

Creating a variable so we can establish when drawing should occur on the canvas.

let lastX = 0;
let lastY = 0;
Enter fullscreen mode Exit fullscreen mode

This is the beginning to establishing where our line ended on the canvas screen. It's giving us kind of a starting point, which we will make malleable with more script.

function draw (e) {
  console.log(e);
}

canvas.addEventListener('mousemove', draw);
Enter fullscreen mode Exit fullscreen mode

This function and event listener is the beginning to us tracking where the mouse is on the canvas so when we write more script we can determine where the drawing should occur.

Mouseover console log

See the console log for all of the events it's tracking when my mouse moves around the canvas space.

function draw (e) {
  if(!isDrawing) return; // stop fn when not moused down
  console.log(e);
}
Enter fullscreen mode Exit fullscreen mode

We added an if statement so the function will not run when the mouse is not clicked down. We will be adding the click down later on.

canvas.addEventListener('mousedown', () => isDrawing = true);
canvas.addEventListener('mouseup', () => isDrawing = false);
canvas.addEventListener('mouseout', () => isDrawing = false);
Enter fullscreen mode Exit fullscreen mode

Now we can add the additional event listeners for the different mouse actions. mousedown will initiate the drawing. mouseup and mouseout will cease the drawing. So that should cover everything for our click and drag function.

ctx = everything to do with our drawing

  ctx.beginPath();
  ctx.moveTo(lastX, lastY);
  ctx.lineTo(e.offsetX, e.offsetY);
  ctx.stroke();
Enter fullscreen mode Exit fullscreen mode

All of these ctx will get us started with our line, but it won't quite get us all the way there.

ctx line work

As you can see everything is starting from a 0 of the Y and X axis.

  lastX = e.offsetX;
  lastY = e.offsetY;
Enter fullscreen mode Exit fullscreen mode

So we added some code to adjust where the beginning/end should be for our mouse click. BUT it's still not fully functioning as we want because it's creating one continuous line now.

last=offset continuous line

  [lastX, lastY] = [e.offsetX, e.offsetY];
Enter fullscreen mode Exit fullscreen mode

Simplified the code using destructuring an array, now we can move on...

canvas.addEventListener('mousedown', (e) => {
  isDrawing = true;
  [lastX, lastY] = [e.offsetX, e.offsetY];
});
Enter fullscreen mode Exit fullscreen mode

We took our mousedown event listener and updated it accordingly, so that it can direct where the click points are occurring on the canvas. Something I missed the first time around was making sure we passed the event (e).

passed the event thru the mousedown event listener

ctx.strokeStyle = '#BADA55';
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.lineWidth = 100;
Enter fullscreen mode Exit fullscreen mode

In addition to our other ctx visual appearances, we could update the width of the line we are drawing.

Thick and ugly green color

Now it's time to play with colors, we'll be using HSL.
mothereffinghsl.com

let hue = 0;
Enter fullscreen mode Exit fullscreen mode

To our other let variables we'll add the hue. This will start us at 0 aka red. And if you go look at the hsl website above you'll see what happens when you uptick the hsl number from 0 to 360.

ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`;
Enter fullscreen mode Exit fullscreen mode

Inside of our draw function we will set the strokeStyle (instead of it being the ugly badass green). It pulls in our hue variable, which is set to red/0.

stokeStyle set hue to 0 red

hue++;
Enter fullscreen mode Exit fullscreen mode

Still inside our draw function, at the end, we set the hue to increment. This is where it gets fun! Check out the rainbow.

Hue rainbow drawing

  hue++;
  if (hue >= 360) {
    hue = 0;
  }
Enter fullscreen mode Exit fullscreen mode

So that the hue can reset back to 0, we want to add an if statement. Now I'm not fully sure why it may need to be reset as it seems to just keep cycling through all the colors, even if the number surpasses 360.

ctx.lineWidth = hue;
Enter fullscreen mode Exit fullscreen mode

Now we are messing with the lineWidth. Adding this ctx within the draw function still under the strokeStyle.

lineWidth grows in size

It sort of is jumping from large back to small at a certain point, so we want the size to eb and flow instead.

let direction = true;
Enter fullscreen mode Exit fullscreen mode

Create another variable with all of our other let variables.

So we will remove the ctx.lineWidth = hue that we created before and we will build off of this new variable we created instead.

ctx.lineWidth++;
Enter fullscreen mode Exit fullscreen mode

Like our hue, we will start with creating an incrementing variable. BUT the problem at this point is that it just gets bigger indefinitely... until it jumps back down to small again.

ctx.lineWidth++;

  if(ctx.lineWidth >= 100 || ctx.lineWidth <= 1) {
    direction = !direction;
  }
  if(direction) {
  ctx.lineWidth++;;
  } else {
    ctx.lineWidth--;
  }
Enter fullscreen mode Exit fullscreen mode

Instead we want to replace it with a couple if statements. The first if statement not allowing it to get too big or too small. The second if statement telling it to get larger and then smaller.

NOW... something isn't working in my code, so I missed something. One moment for some debugging.

  // ctx.lineWidth = hue;
Enter fullscreen mode Exit fullscreen mode

Aha... I forgot to delete or comment out the ctx.lineWidth = hue, even tho I discussed it earlier!

For funsies you can add ctx.globalCompositeOperation and there's lots of paint brush filter options.

I put 'overlay' on mine!

ctx.globalCompositeOperation = 'overlay';
Enter fullscreen mode Exit fullscreen mode

ctx.globalCompositeOperation = 'overlay';

It would be pretty cool to combine this lesson with the lesson from Day 3! And potentially add some background options, so you could give people coloring books.

Check out the canvas live here!

That was a lot of fun. Have you ever done a project like this? Anything you may recommend me to do? Comment below! I'd love to hear from you.

Top comments (0)