Skip to content

Build a Signature Pad in ReactJS with HTML5 Canvas

Posted on:July 16, 2023 at 10:20 PM

If you prefer to build a signature pad in React.js without using an external library, you can implement it using HTML5 canvas and React’s state management. Here’s an example of how you can achieve this.

Table of contents

Open Table of contents

Set up a new React.js project

 npx create-react-app signature-pad
cd signature-pad

Implement the signature pad component

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

const App = () => {
  const [isDrawing, setIsDrawing] = useState(false);
  const canvasRef = useRef(null);
  const contextRef = useRef(null);

  const startDrawing = ({ nativeEvent }) => {
    const { offsetX, offsetY } = nativeEvent;
    setIsDrawing(true);
    contextRef.current.beginPath();
    contextRef.current.moveTo(offsetX, offsetY);
  };

  const finishDrawing = () => {
    setIsDrawing(false);
  };

  const draw = ({ nativeEvent }) => {
    if (!isDrawing) return;
    const { offsetX, offsetY } = nativeEvent;
    contextRef.current.lineTo(offsetX, offsetY);
    contextRef.current.stroke();
  };

  const clearCanvas = () => {
    contextRef.current.clearRect(
      0,
      0,
      canvasRef.current.width,
      canvasRef.current.height
    );
  };

  const saveSignature = () => {
    const imageDataURL = canvasRef.current.toDataURL();
    // Do something with the imageDataURL (e.g., save it, send it to the server, etc.)
    console.log(imageDataURL);
  };

  // Initialize the canvas context
  React.useEffect(() => {
    const canvas = canvasRef.current;
    canvas.width = canvas.offsetWidth;
    canvas.height = canvas.offsetHeight;
    const context = canvas.getContext("2d");
    context.scale(1, 1);
    context.lineCap = "round";
    context.lineWidth = 2;
    contextRef.current = context;
  }, []);

  return (
    <div>
      <canvas
        ref={canvasRef}
        onMouseDown={startDrawing}
        onMouseUp={finishDrawing}
        onMouseMove={draw}
        style={{ border: "1px solid black" }}
      />
      <div>
        <button onClick={clearCanvas}>Clear</button>
        <button onClick={saveSignature}>Save</button>
      </div>
    </div>
  );
};

export default App;

Run the application

In this implementation, we use the useState hook to manage the state of the drawing process. The isDrawing state determines whether the user is currently drawing on the canvas. The canvasRef and contextRef references allow us to access the canvas element and its 2D context.

The event handlers, startDrawing, finishDrawing, and draw, handle the mouse events on the canvas. When the user clicks down, we begin a new path using beginPath and move the cursor to the clicked position. When the user releases the mouse button, we end the drawing process. The draw function is called continuously while the mouse is moved, creating a smooth drawing effect by connecting the previous and current positions with lines.

The clearCanvas function clears the canvas by using clearRect on the canvas context, effectively erasing any