When I was trying Canvas, I was completely puzzled. It felt so frustrating; I felt like I was writing in a completely different language instead of my usual JavaScript. But after reading the MDN doc and watching some videos...it still feels difficult and frustrating. But despite everything, let's try to build something. Polishing can come later.
First, we need to select the ID from HTML
const canvas = document.querySelector("#draw");
We need canvas.getContext here to tell the browser what type of drawing we are going to do. For now, the screen is blank, so we need to tell it what we are going to do. The <canvas> element has a method called getContext. That's the one we are targeting here
const ctx = canvas.getContext("2d");
We are going to draw on the whole window, so we need to target the whole window. But we can't just let HTML decide the window. We need to overwrite it, and JavaScript can help here with its innerHeight and innerWidth properties
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
That's a lot. I know. So, let's slow down and draw our first rectangle.
function draw() {
const canvas = document.querySelector("#draw");
const ctx = canvas.getContext("2d");
ctx.fillStyle = "rgb(200 0 0 / 50%)"; // setting the rect color with the fillStyle property
ctx.fillRect(10, 10, 50, 50); // drawing the rectangle using the fillRect canvas api's method
}
draw();
That was easy, but we are not going to draw shapes. Our goal is to use freehand. Comment out or delete the previous draw function.
For now, we need four things before going forward. Set the color of the pen, how we want our pen to be, how the ends of lines look, and the size of the pen.
ctx.strokeStyle = "rgb(200 135 90)";
ctx.lineJoin = "round";
ctx.lineCap = "round";
ctx.lineWidth = 5;
Here we can set the pen color with strokeStyle, how corners between connected lines look with lineJoin, the ending of the lines with lineCap (default to butt), and the size with lineWidth.
We don't want to draw with every movement our mouse do. Only when we click the mouse and move it. So here it is
let isDrawing = false;
let lastX = 0;
let lastY = 0;
lastX/Y start at 0 as a placeholder. Later, they get replaced by the real mouse X/Y position from e.offsetX/Y.
Let's draw it now:
function draw(e) {
if (!isDrawing) return;
console.log(e);
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
[lastX, lastY] = [e.offsetX, e.offsetY];
}
The condition prevents drawing when the mouse button is not being held down
beginPath() starts a new path every time
moveTo() sets the starting point of the line
lineTo() draws a line from the current point to the current mouse position
stroke() draws the path onto the canvas using the current stroke settings
[lastX, lastY] = [e.offsetX, e.offsetY] updates to the current mouse position by destructuring
// Mouse button pressed down β start drawing
canvas.addEventListener("mousedown", (e) => {
isDrawing = true;
[lastX, lastY] = [e.offsetX, e.offsetY];
});
// Mouse button released β stop drawing
canvas.addEventListener("mouseup", () => {
isDrawing = false;
});
// Mouse leaves canvas β also stop
canvas.addEventListener("mouseout", () => {
isDrawing = false;
});
// Mouse moves β only draw if the flag is true
canvas.addEventListener("mousemove", draw);
That's it for today. Tada! Leave a comment if you want to.
Further reading:
Top comments (0)