{
  "id": 15115438,
  "title": "How I built a live halftone portrait in React with just Canvas 2D",
  "url": "https://urgent.news/2026/10/17/how-i-built-a-live-halftone-portrait-in-react-with-just-canvas-2d",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-10-17T04:12:03.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/suraj_nandan_dcd78e7ec898/how-i-built-a-live-halftone-portrait-in-react-with-just-canvas-2d-5ejg"
  },
  "original_language": "en",
  "account": "The author wanted their portfolio's photo to resemble a halftone print, featuring a grid of dots that vary in size based on lightness and darkness. They achieved this using just 150 lines of React and the Canvas 2D API without any dependencies. The process is broken down into four steps.\n\nFirst, the image is transformed into a grid of samples, essentially creating a low-resolution version of the picture made of dots. This is done by drawing the image onto a small offscreen canvas and reading the pixels back using getImageData. The browser handles the downscaling by averaging the source pixels for each sample, which provides the color and darkness needed for each dot.\n\nNext, a dot is drawn for each sample. The radius of each dot is determined by the sample's darkness, with darker samples resulting in larger dots. A tone curve is applied to the darkness value to prevent midtones from appearing too light. Additionally, an elliptical vignette is used to give the portrait a soft edge instead of a hard rectangle.\n\nTo add a sense of life to the portrait, a small sine wave is introduced, causing each dot to ripple slightly based on its position. This ripple effect is relatively slow, making the portrait appear to breathe.\n\nFinally, the portrait reacts to the cursor. The cursor's position is smoothed out and targeted, causing the dots to grow or shrink as the cursor moves around them. This creates an interactive experience where the dots appear to swell and recede as the cursor moves over them.",
  "summary": "My portfolio is set like a newspaper, so my photo couldn't just be a photo. I wanted it to look like a printed halftone: a grid of dots, bigger where the picture is dark and smaller where it's light. And I wanted it to be alive, so the dots swell and get pushed away when you move the cursor over them. It turned out to be about 150 lines of React and plain Canvas 2D, with no dependencies. Here's…",
  "key_points": [
    "Image transformed into low-resolution grid of dots using Canvas 2D API",
    "Dot radius determined by sample darkness with applied tone curve",
    "Cursor interaction causes dots to swell and recede in a breathing effect"
  ],
  "editors_take": "Leveraging the native Canvas 2D API to create complex visual effects demonstrates how developers can build interactive, high-performance artistic components without the overhead of external dependencies.",
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}