How to Create Draggable Canvas Element in React 18

Last Updated on by in React JS

How to Create Draggable Canvas Element in React

Draggable canvas refers to the capability of making elements within an HTML5 canvas interactive and movable through drag-and-drop functionality, adding a sense of action and movement. HTML5 canvas is a powerful element used in web development to draw graphics, animations, and visual elements using JavaScript.

In this post, we will learn how to create a draggable canvas element in a React application using function component, HTML5 canvas API and canvas event handler methods.

React HTML5 Draggable Canvas Example

Drag-and-drop is an essential feature in web development that permits users to interact with websites, applications, and software by allowing the manipulation of UI elements through a click, hold, and movement gesture.

It simplifies complex tasks by enabling re-ordering and rearrangement of elements, adding a sense of movement and action to UI elements on web pages, resulting in captivating, engaging, and streamlined user interactions.

This quick guide focuses on how to create a draggable canvas using simple JavaScript canvas APIs with React function component, including JavaScript event handlers to track mouse movements and interactions that give users the ability to manipulate objects inside the HTML5 draggable canvas dynamically.

Let’s embark on a journey to implement and build draggable canvas functionality, and learn how to lay down, show and move the HTML elements on the draggable canvas component in React.

Build React Project

You have setup Node and npm in your system; it allows you to create a new React app.

To install React framework, you have to open command prompt, add the command and run the below command.

npx create-react-app my-react-app

Now, navigate to the project folder:

cd my-react-app

Install Bootstrap Library

This step is utterly optional; we are using bootstrap to design the basic layout and useful UI components.

npm install bootstrap --legacy-peer-deps

Create Function Component

Next, create a new components/, then you need to create CanvasDrag.js file.

import React from 'react'

function CanvasDrag() {
  return (
    <div></div>
  )
}

export default CanvasDrag

Build Canvas Draggable Component

The following code guides on: How to start and set the canvas context, assign dynamic dimensions and draw and drag canvas elements.

You have to open the components/CanvasDrag.js file.

import React, { useRef, useEffect } from "react";

function CanvasDrag() {
  const canvas = useRef();
  let getCtx = null;
  const canBoxes = [
    { x: 190, y: 250, w: 120, h: 70 },
    { x: 110, y: 115, w: 100, h: 70 },
  ];
  let isMoveDown = false;
  let targetCanvas = null;
  let startX = null;
  let startY = null;

  useEffect(() => {
    const canvasDimensions = canvas.current;
    canvasDimensions.width = canvasDimensions.clientWidth;
    canvasDimensions.height = canvasDimensions.clientHeight;
    getCtx = canvasDimensions.getContext("2d");
  }, []);

  useEffect(() => {
    canvasDraw();
  }, []);

  const canvasDraw = () => {
    getCtx.clearRect(
      0,
      0,
      canvas.current.clientWidth,
      canvas.current.clientHeight,
    );
    canBoxes.map((info) => fillCanvas(info));
  };

  const fillCanvas = (info, style = {}) => {
    const { x, y, w, h } = info;
    const { backgroundColor = "#D75755" } = style;

    getCtx.beginPath();
    getCtx.fillStyle = backgroundColor;
    getCtx.fillRect(x, y, w, h);
  };

  const moveableItem = (x, y) => {
    let isCanvasTarget = null;
    for (let i = 0; i < canBoxes.length; i++) {
      const block = canBoxes[i];
      if (
        x >= block.x &&
        x <= block.x + block.w &&
        y >= block.y &&
        y <= block.y + block.h
      ) {
        targetCanvas = block;
        isCanvasTarget = true;
        break;
      }
    }
    return isCanvasTarget;
  };

  const onMouseDown = (e) => {
    startX = parseInt(e.nativeEvent.offsetX - canvas.current.clientLeft);
    startY = parseInt(e.nativeEvent.offsetY - canvas.current.clientTop);
    isMoveDown = moveableItem(startX, startY);
  };
  const onMouseMove = (e) => {
    if (!isMoveDown) return;

    const mouseX = parseInt(e.nativeEvent.offsetX - canvas.current.clientLeft);
    const mouseY = parseInt(e.nativeEvent.offsetY - canvas.current.clientTop);
    const mouseStartX = mouseX - startX;
    const mouseStartY = mouseY - startY;
    startX = mouseX;
    startY = mouseY;
    targetCanvas.x += mouseStartX;
    targetCanvas.y += mouseStartY;
    canvasDraw();
  };
  const onMouseUp = (e) => {
    targetCanvas = null;
    isMoveDown = false;
  };
  const onMouseOut = (e) => {
    onMouseUp(e);
  };

  return (
    <div>
      <canvas
        onMouseDown={onMouseDown}
        onMouseMove={onMouseMove}
        onMouseUp={onMouseUp}
        onMouseOut={onMouseOut}
        ref={canvas}
      ></canvas>
    </div>
  );
}

export default CanvasDrag;

Update App Js File

The App.js file is solely responsible for creating the structure and behavior of our React application components.

Here is why, we have to register previously built component into the App.js file.

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import CanvasDrag from "./components/CanvasDrag";

function App() {
  return (
    <div className="container mt-3">
      <h2 className="mb-3">React Canvas Draggable Shapes Example</h2>
      <CanvasDrag />
    </div>
  );
}

export default App;

Start React Server

Navigate to the console, type below command and press enter to run the app.

npm start

The above command starts the app on the browser:

http://localhost:3000

Conclusion

In conclusion, allowing elements to be draggable on a canvas can greatly enhance the user experience and interactivity of modern web applications.

React’s state management system permits seamless integration of draggable components, and its reusable component system offers a flexible way for creating dynamic interfaces.

In this tutorial, we have learned how to create a simple draggable canvas element that can be moved using a React component.

If you want to know more about The Graphics Canvas element and dive deep into the worlds of Canvas API, make sure to check out the Canvas APIs.

Digamber - Author positronX.io

Hi, I'm Digamber Singh, a New Delhi-based full-stack developer, tech author, and open-source contributor with 10+ years' experience in HTML, CSS, JavaScript, PHP, and WordPress.