Draw Rectangle on Mouse & Touch Events – JavaScript Canvas

Draw Rectangle on Mouse & Touch Events – JavaScript Canvas

In this tutorial, I will guide you on how to draw rectangles on Mouse and Touch Events on Canvas. This is a step-by-step guide on JavaScript Canvas rectangle drawing to make you understand what actually happens in each part of the code.

Table of Contents:

What is Canvas?

Canvas is an element that acts as a container, Imagine it as a plain board. Canvas itself is not a drawing container, you can only draw shapes by accessing the context API in JavaScript by using getContext('2d') that returns the reference to the 2D context inside the canvas.

<canvas id="drawContainer" width="1000" height="1000" 
style="border: 1px solid #333"></canvas>

It’s important for a canvas element to have width and height attributes defined in HTML. If you change the canvas width and height by using CSS width and height properties, the canvas will only scale up and down (not recommended).

Three Ways to Draw Rectangle on Canvas

To draw any shapes on Canvas, we should get the 2d context of the canvas.

const canvasEle = document.getElementById('drawContainer');
const context = canvasEle.getContext('2d');

To draw rectangles on Canvas, there are three canvas methods available:

1. Draw a Rectangle using Context.rect method

Using Context.rect we can draw a rectangle but we have to call the fill() and stroke() methods to make the rectangle visible with background and borders.

context.strokeStyle = "brown"; // add blue color to the border
context.lineWidth = 10; // increase the border width
context.fillStyle = "orange"; // add background color to shape
context.rect(50, 50, 200, 200); // configure rectangle coordinates, width and height
context.stroke(); // drawing of bordered rectangle
context.fill(); // drawing of background in rectangle

2. Draw a Rectangle using Context.fillRect method

Using Context.fillRect, you can draw a rectangle with background color filled. It internally calls the fill() method to add background to the rectangle shape.

context.fillStyle = "red"; // add background color
context.fillRect(300, 50, 200, 200); // configure rectangle coordinates, width and height

3. Draw a Rectangle using Context.strokeRect method

Using Context.strokeRect, you can draw a rectangle with stroked border color. It internally calls stroke() method to add stroke/border color to the rectangle shape.

context.strokeStyle = "green"; // add border color
context.strokeRect(550, 50, 200, 200); // draw rectangle with border only
Rectangle drawing preview in canvas
rect method
Rectangle drawing preview in canvas  using fillrect method
fillRect method
Rectangle drawing preview in canvas  using strokeRect method
strokeRect method

All the rectangle drawing methods have common parameters: x, y, width, and height.

  1. X – the x coordinate of the canvas to define where the rectangle shape should start drawing in the horizontal place.
  2. Y – the y coordinate of the canvas to define where the rectangle shape should start drawing in the vertical place
  3. width – The width of the rectangle in pixels.
  4. height -The height of the rectangle in pixels.

Let’s dive into how to draw the rectangle using mouse events.

How to Draw Rectangles using Mouse and Touch Events?

We are going to use the following events for drawing rectangles on the canvas.

  • mousedown – triggered by clicking the mouse button.
  • mousemove – triggered whenever you move the mouse.
  • mouseup – triggered when you release the mouse button.
  • touchstart – triggered by touching the canvas.
  • touchmove – triggered whenever you move your finger on the screen.
  • touchend – triggered when you release the touch.

Here’s a full code on how to draw a rectangle in javascript canvas using mouse and touch events

const canvasEle = document.getElementById('drawContainer');
const context = canvasEle.getContext('2d');
let isDrawStart = false;
let startPosition = {x: 0, y: 0};
let endPosition = {x: 0, y: 0};

const getClientOffset = (event) => {
    const {pageX, pageY} = event.touches ? event.touches[0] : event;
    const x = pageX - canvasEle.offsetLeft;
    const y = pageY - canvasEle.offsetTop;

    return {
       x,
       y
    } 
}

const drawRectangle = (width, height) => {
  context.beginPath();
  context.strokeStyle = "brown"; 
  context.lineWidth = 10;
  context.fillStyle = "orange";
  context.rect(startPosition.x, startPosition.y, width, height);
  context.stroke();
  context.fill();
}

const clearCanvas = () => {
   context.clearRect(0, 0, canvasEle.width, canvasEle.height);
}

const mouseDownListener = (event) => {
   startPosition = getClientOffset(event);
   isDrawStart = true;
}

const mouseMoveListener = (event) => {
  if(!isDrawStart) return;
  
  endPosition = getClientOffset(event);
  const width = endPosition.x - startPosition.x;
  const height = endPosition.y - startPosition.y;
  clearCanvas();
  drawRectangle(width, height);
}

const mouseupListener = (event) => {
  isDrawStart = false;
}

canvasEle.addEventListener('mousedown', mouseDownListener);
canvasEle.addEventListener('mousemove', mouseMoveListener);
canvasEle.addEventListener('mouseup', mouseupListener);

canvasEle.addEventListener('touchstart', mouseDownListener);
canvasEle.addEventListener('touchmove', mouseMoveListener);
canvasEle.addEventListener('touchend', mouseupListener);

Let’s dig dive into what’s happening in each part of the code to get a clear understanding of the concept behind the drawing.

Declare 3 variables at the start of the file:

let isDrawStart = false;
let startPosition = {x: 0, y: 0};
let endPosition = {x: 0, y: 0};
  1. isDrawStart – A boolean to check if the drawing has started by mousedown event or not. The mouseMove event triggers too often, so we are using this boolean to detect whether we can draw or not.
  2. startPosition – The startPosition variable holds the value of the starting position of the drawing. On mousedown event, we are going to update the x and y values as objects to this variable.
  3. endPosition – The endPosition variable holds the value of the end position of the drawing. On mouseup event, we are going to update x and y values as objects to this variable by detecting where we end up the drawing in the canvas

Listen for Mouse and Touch Events

canvasEle.addEventListener('mousedown', mouseDownListener);
canvasEle.addEventListener('mousemove', mouseMoveListener);
canvasEle.addEventListener('mouseup', mouseupListener);

canvasEle.addEventListener('touchstart', mouseDownListener);
canvasEle.addEventListener('touchmove', mouseMoveListener);
canvasEle.addEventListener('touchend', mouseupListener);

In the above code, We are listening for all the events and adding relevant event listener functions for the events as well. We are going to use the same relevant functions for mouse and touch events. For example, mousedown and touchstart are doing the same thing that is to trigger the handler function on the touch/mouseclick of the DOM so we are using the mouseDownListener function.

Calculate the Drawing Coordinates of Rectangle Shape

const getClientOffset = (event) => {
    const {pageX, pageY} = event.touches ? event.touches[0] : event;
    const x = pageX - canvasEle.offsetLeft;
    const y = pageY - canvasEle.offsetTop;

    return {
       x,
       y
    } 
}

The getClientOffset function is used to get the exact coordinates of x and y axis when the user clicks or touches the JavaScript canvas. To detect the exact location of the x and y axis in the canvas element, we should subtract pageX and pageY of the mouse event or touch events with the canvas element offsetLeft and offsetTop.

The pageX and pageY are the horizontal and vertical coordinates of the mouse click/touch. The offsetLeft and offsetTop returns the left and the top position in pixels relative to the nearest parent. In our example, it’s relative to the body since we don’t have any wrapper around our HTML canvas element.

Calculate the Starting Coordinates on Mouse Down Event

const mouseDownListener = (event) => {
   startPosition = getClientOffset(event);
   isDrawStart = true;
}

The mouseDownListener function will be triggered on the mousedown event. It calculates the starting position coordinates by triggering our reusable coordinate calculator function getClientOffset with the event object as a parameter and returns the x and y coordinates as an object. We are storing the value in the startPosition variable.

We are making isDrawStart to true to let other functions know that drawing has started.

Calculate the End Position Coordinates on Mouse Move Event

const mouseMoveListener = (event) => {
  if(!isDrawStart) return;
  
  endPosition = getClientOffset(event);
  const width = endPosition.x - startPosition.x;
  const height = endPosition.y - startPosition.y;
  clearCanvas();
  drawRectangle(width, height);
}

The mouseMoveListener is attached as a handler function for mousemove and touchmove events. At the very start of the function, we are checking if the drawing is started or not by using the isDrawStart variable.

If isDrawStart is false, we return from the function. If isDrawStart is true, we are calculating the end position of the rectangle coordinates by using our getClientOffset function and store the returning x and y coordinates object in endPosition variable.

To calculate the width and height for the rectangle, we are subtracting the end position of x and y with the start position of x and y we stored on the mouse down event.

The next step is to draw the rectangle using the drawRectangle method with proper width and height using our coordinates.

Draw Rectangle Using Calculated Width and Height

const drawRectangle = (width, height) => {
  context.beginPath();
  context.strokeStyle = "brown"; 
  context.lineWidth = 10;
  context.fillStyle = "orange";
  context.rect(startPosition.x, startPosition.y, width, height);
  context.stroke();
  context.fill();
}

The drawRectangle method accepts calculated width and height as parameters. Using the startPosition x, and y coordinates and calculated width and height from the mousemove event, we are defining where the rectangle drawing should happen. The strokeStyle and fillStyle properties are used to add the border and background color for the rectangle.

In the above example, I have used the context.rect(x, y, width, height) method to draw rectangles. We can also do the same by using context.fillRect(x, y, width, height) or context.strokeRect(x, y, width, height) based on our requirement on what type of rectangle we need.

Clear JavaScript Canvas and Remove Rectangle Drawing

const clearCanvas = () => {
   context.clearRect(0, 0, canvasEle.width, canvasEle.height);
}

In the mousemove event listener function we have invoked the clearCanvas() method that works as an eraser and clears the entire canvas by using the context.clearRect(x, y, width, height) method.

If you want multiple rectangles to be drawn on a canvas, you can comment or remove clearCanvas() method from mousemove event listener function.

Stop Drawing a Rectangle on Mouse Up and Touch End Events

const mouseupListener = (event) => {
  isDrawStart = false;
}

To stop drawing the rectangle, we set the isDrawStart to false when the user leaves the mouse or touch screen. so that further mouse move (touch move) events will not execute the drawing.

CodePen Demo – Draw Rectangle on Mouse Events Demo

See the Pen
Draw Rectangle in Canvas on Mouse Events – ProDevHub.com
by Nithya Rajan (@bearnithi)
on CodePen.0

Conclusion

You May Also Like: JavaScript Canvas – Draw a Line in canvas using Mouse and Touch events

In this detailed step-by-step guide on drawing rectangles, we have covered three different ways to draw rectangles on canvas, and also we learned how we can make use of mouse events and draw the rectangle by calculating the width and height of the rectangle from the coordinates x and y of the event object. I hope this helps to solve your problem, If you are stuck or need any help regarding this implementation, feel free to comment here.