25
Componentregistry:component

Halftone Image

Renders any image as a print-style dot, line or square halftone on a canvas, with controls for dot size, screen angle, ink colour, contrast and inversion. Exports drawHalftone for PNG export.

Installation

$ npx shadcn@latest add @creative-ui/halftone-image

On an older shadcn CLI, use the URL: npx shadcn@latest add https://ui.krutikraut.com/r/halftone-image.json

Preview

Image
Shape
Dot size6px
Angle45°
Contrast1.1
Ink

Usage

Example.tsx
import { HalftoneImage } from "@/components/halftone-image"

export function Hero() {
  return (
    <HalftoneImage
      src="https://images.unsplash.com/photo-1566054757965-8c4085344c96?w=900&q=80&auto=format&fit=crop"
      alt="Marble statue"
      dotSize={6}
      angle={45}
      color="#1d3fb0"
      className="aspect-[4/5] w-80 rounded-xl"
    />
  )
}

Props

PropTypeDefaultDescription
src*string—Image URL. Cross-origin images must be served with CORS headers, or the canvas cannot read them.
altstring""Accessible description. Leave empty for decorative images.
dotSizenumber6Screen pitch in CSS pixels. Smaller is finer.
anglenumber45Screen angle in degrees. 45 is the classic print angle.
shape"dot" | "line" | "square""dot"Mark used for the screen.
colorstring"currentColor"Ink colour. Any CSS colour. currentColor follows the text colour and re-inks when the theme changes.
backgroundstring"transparent"Paper colour behind the marks.
invertbooleanfalseScreen the highlights instead of the shadows, for light ink on dark paper.
contrastnumber1Tone curve steepness, roughly 0.5 to 2.
gainnumber1.15Largest mark relative to the cell. 1 means marks just touch; above 1 lets shadows close up.
fit"cover" | "contain""cover"How the source fills the canvas.
crossOrigin"anonymous" | "use-credentials""anonymous"Pass undefined for same-origin images that must not send a CORS request.
onRendered() => void—Called after each draw.
childrenReact.ReactNode—Content layered over the halftone, such as captions or badges.

Also accepts every div prop, which is spread onto the root element.

Also exported

drawHalftone(canvas, image, width, height, options?)
The renderer on its own, with no React. Draws an image, canvas, video or ImageBitmap onto a canvas, so you can export a PNG with canvas.toBlob(). Takes the same options as the component; color defaults to #111 here.

Notes

  • Size it like an image: give it a width with className. Without a height or aspect ratio it adopts the source image's aspect ratio once loaded.
  • Redraws on resize and caps the device pixel ratio at 2 to keep large canvases fast.
  • The canvas gets role="img" and your alt as its label, or is hidden from assistive tech when alt is empty.

Dependencies

shadcn/utils