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
.
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>
So our first step is to connect our javascript to the canvas through the id draw
.
const canvas = document.querySelector('#draw');
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');
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;
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';
"Badass" color is a pastel green.
let isDrawing = false;
Creating a variable so we can establish when drawing should occur on the canvas.
let lastX = 0;
let lastY = 0;
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);
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.
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);
}
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);
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();
All of these ctx will get us started with our line, but it won't quite get us all the way there.
As you can see everything is starting from a 0 of the Y and X axis.
lastX = e.offsetX;
lastY = e.offsetY;
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.
[lastX, lastY] = [e.offsetX, e.offsetY];
Simplified the code using destructuring an array, now we can move on...
canvas.addEventListener('mousedown', (e) => {
isDrawing = true;
[lastX, lastY] = [e.offsetX, e.offsetY];
});
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)
.
ctx.strokeStyle = '#BADA55';
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.lineWidth = 100;
In addition to our other ctx visual appearances, we could update the width of the line we are drawing.
Now it's time to play with colors, we'll be using HSL.
mothereffinghsl.com
let hue = 0;
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%)`;
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.
hue++;
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++;
if (hue >= 360) {
hue = 0;
}
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;
Now we are messing with the lineWidth
. Adding this ctx within the draw
function still under the strokeStyle
.
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;
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++;
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.
if(ctx.lineWidth >= 100 || ctx.lineWidth <= 1) {
direction = !direction;
}
if(direction) {
ctx.lineWidth++;;
} else {
ctx.lineWidth--;
}
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;
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';
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)