Draw and Pin on Image

Objective
The feature allows users to draw and pin annotations on an image. The objective is to provide an interactive and collaborative tool for marking and annotating floor plans, blueprints, or images in a web application.

Where It Can Be Used
In many applications, users need the ability to annotate images by adding pins or drawing freehand. This feature is useful in industries such as real estate, construction, and education, where users need to highlight specific areas of an image dynamically. This component integrates image zooming, panning, pinning, and drawing functionalities.

Step-by-Step Explanation

  1. Image Loading and Resizing
    The image is loaded dynamically and resized based on the viewport to maintain a responsive design and user accessibility across devices.
  2. Zoom and Pan (Using react-zoom-pan-pinch)
    This package provides built-in functionality for pinch-to-zoom and dragging (panning) on both mobile and desktop environments. Wrapping the image in TransformWrapper and TransformComponent allows users to zoom in/out and move the image freely without disrupting annotations.
<TransformWrapper>
  <TransformComponent>
    <img src="image.jpg" alt="Annotatable" />
  </TransformComponent>
</TransformWrapper>
  1. Pin Placement and Management
    When the user clicks on the image in pin mode, a pin is placed at the clicked location using cursor coordinates relative to the image position. Each pin is stored in a state array.
const handleImageClick = (e) => {
  if (mode === 'pin') {
    const rect = imageRef.current.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;
    setPins([...pins, { x, y, id: Date.now() }]);
  }
};
  1. Drawing Mode (Using ReactSketchCanvas)
    Allows users to draw on the image freely. Users can choose stroke color, and each stroke is rendered over the image using canvas layers.
<ReactSketchCanvas
  ref={canvasRef}
  strokeColor={selectedColor}
  strokeWidth={4}
/>
  1. Eraser and Reset
    Users can switch to eraser mode to remove specific strokes or clear the entire canvas to reset the drawing.
canvasRef.current.eraseMode(true); // Enable eraser
canvasRef.current.clearCanvas(); // Clear all drawings
  1. Undo/Redo Feature
    Provides control over annotation history by allowing users to undo or redo actions.
canvasRef.current.undo();
canvasRef.current.redo();
  1. Save and Load Annotations
    Pins and drawing paths are serialized and saved (e.g., in localStorage), allowing users to return later and restore their work.
const saveAnnotations = async () => {
  const paths = await canvasRef.current.exportPaths();
  localStorage.setItem('annotations', JSON.stringify({ pins, paths }));
};

const loadAnnotations = async () => {
  const data = JSON.parse(localStorage.getItem('annotations'));
  setPins(data.pins);
  canvasRef.current.loadPaths(data.paths);
};
  1. State Management
    React useState manages the drawing mode, pin list, and current drawing attributes. This ensures real-time UI updates and user interactivity.
  2. UI Controls
    A set of buttons allows toggling between drawing and pinning modes, clearing the canvas, and switching to eraser mode.
<button onClick={() => setMode('draw')}>Draw</button>
<button onClick={() => setMode('pin')}>Pin</button>
<button onClick={() => canvasRef.current.clearCanvas()}>Reset</button>

Resources Needed

  • react-zoom-pan-pinch for zooming and panning.
  • ReactSketchCanvas for drawing.
  • Image assets for pin icons and UI controls.

Findings/Results

  • The component successfully integrates pinning and drawing on images.
  • The zoom and pan functionalities work as expected without interfering with annotations.
  • The undo, redo, erase and reset functionality improves user experience.
  • Saving and loading annotations enhance workflow efficiency.

Documentation and References

7 Likes