Hone logo
Hone
Problems

React Annotation Tool

This challenge asks you to build a basic annotation tool using React and TypeScript. The tool will allow users to draw rectangles on an image and save the coordinates of those rectangles. This is a common feature in image editing applications, data labeling platforms, and other visual tools, making it a valuable exercise in component design and state management.

Problem Description

You are tasked with creating a React component that displays an image and allows users to draw rectangular annotations on it. The component should:

  1. Display an Image: Render an image from a provided URL.
  2. Drawing Functionality: Allow users to click and drag to create rectangular annotations. The rectangle should be visually displayed on the image as the user drags.
  3. State Management: Store the coordinates (x1, y1, x2, y2) of the currently drawn rectangle in the component's state. If no rectangle is being drawn, the state should be null.
  4. Clear Annotation: Provide a button to clear the current annotation, resetting the state to null.
  5. Save Annotation (Placeholder): Include a button labeled "Save" that, for this challenge, simply logs the annotation coordinates to the console when clicked. (Full saving functionality is beyond the scope of this exercise).
  6. Error Handling: Display an error message if the image URL is invalid or if the image fails to load.

Expected Behavior:

  • When the user clicks and drags, a rectangle should appear, dynamically resizing based on the mouse position.
  • The rectangle's position should be updated in real-time as the user drags.
  • Clicking the "Clear" button should remove the rectangle and reset the state.
  • Clicking the "Save" button should log the rectangle coordinates to the console.
  • If the image fails to load, an appropriate error message should be displayed.

Edge Cases to Consider:

  • Invalid Image URL: Handle cases where the provided image URL is incorrect or inaccessible.
  • Zero-Sized Rectangle: Ensure the rectangle coordinates are valid (x1 < x2 and y1 < y2). You can either prevent the user from creating such rectangles or handle them gracefully.
  • Dragging Outside Image Boundaries: Consider how the rectangle should behave if the user drags it outside the image boundaries. Clipping to the image boundaries is a reasonable approach.
  • Performance: While not a primary concern for this basic tool, be mindful of potential performance issues if the image is very large.

Examples

Example 1:

Input: imageURL = "https://via.placeholder.com/600x400", initialAnnotation = null
Output: A React component displaying the placeholder image with a rectangle drawn from (100, 50) to (300, 200) as the user drags the mouse.
Explanation: The user clicked at (100, 50) and dragged to (300, 200), creating a rectangle with those coordinates.

Example 2:

Input: imageURL = "invalid_url", initialAnnotation = null
Output: A React component displaying an error message: "Error: Could not load image."
Explanation: The image URL is invalid, so the component displays an error message instead of the image.

Example 3:

Input: imageURL = "https://via.placeholder.com/600x400", initialAnnotation = {x1: 50, y1: 25, x2: 150, y2: 125}
Output: A React component displaying the placeholder image with a rectangle already drawn from (50, 25) to (150, 125).
Explanation: The component initializes with a pre-defined annotation.

Constraints

  • Image Size: The image can be up to 2000x2000 pixels.
  • Coordinate Range: Rectangle coordinates should be within the bounds of the image.
  • Dependencies: You are allowed to use standard React and TypeScript features. External libraries for drawing are not permitted for this challenge. Focus on core React concepts.
  • Performance: The component should remain responsive during dragging operations. Avoid unnecessary re-renders.

Notes

  • Consider using useState for managing the annotation coordinates.
  • Use event listeners (e.g., onMouseDown, onMouseMove, onMouseUp) to handle the drawing logic.
  • Think about how to efficiently update the rectangle's position as the user drags the mouse.
  • You can use CSS to style the rectangle.
  • The "Save" button is a placeholder; you don't need to implement actual saving functionality. Simply log the coordinates to the console.
  • Focus on creating a functional and visually clear annotation tool. Clean code and good component structure are important.
Loading editor...
typescript