KQ-1594 · LIQUIFY/PRINT
Liquify Print
A print you push around like wet paint: a drag smears the picture along the stroke through a WebGL2 displacement field, circling winds the paint into a small vortex, and fresh smears shine wet where the paint was worked. When the hand stops, the print relaxes back to itself on a critically damped ease over `relax` ms, as if the paint remembered its shape; smears made with Shift held are pinned in a second field and stay, and double click or Escape restores everything on the snap spring. The print is focusable: arrow keys smear from a brush at its centre, Shift pins, the bracket keys twist, P pins every smear and Escape restores.
Fernworks Press · Fern study
print at rest · drag to smear
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/liquify-print
Props
- src
- string
- default —
- An image to smear instead of the drawn print; for WebGL it must be same-origin or CORS.
- alt
- string
- default —
- What the print shows, for assistive technology.
- brush
- number
- default 56
- The brush's radius in px.
- relax
- number
- default 2200
- How long the paint takes to remember its shape once you stop, in ms.
- gloss
- number
- default 0.55
- How wet a fresh smear looks: dry and matte (0) to a sheen that dries as it relaxes (1).
- strength
- number
- default 1
- How much paint a stroke carries, 0 to 1.5.
- swirl
- number
- default 0.6
- How much a circling stroke winds the paint into a vortex, 0 to 1.
- pinned / defaultPinned
- boolean
- default false
- Pin every smear so none relax.
- onPinnedChange
- (pinned: boolean) => void
- default —
- Fires when the pin is switched (the P key), with the new state.
- onSmear
- (pinned: boolean) => void
- default —
- Fires as a stroke starts, with whether it is pinned.
- onRestore
- () => void
- default —
- Fires when the print is restored by a double click, Escape or restoreKey.
- onStateChange
- (state: LiquifyPrintState) => void
- default —
- Fires as the print goes between rest, smearing, relaxing and holding.
- restoreKey
- number
- default 0
- Change it to restore the print from outside.
- label
- string
- default "Wet print"
- Names the print for assistive technology.
- disabled
- boolean
- default false
- Shows the print but takes no input.
- dpr
- number
- default 2
- Cap on the canvas's device pixel ratio, at most 2.
- className
- string
- default "h-56 w-full"
- Sizes the print; give it a height.
| Prop | Type | Default | Description |
|---|---|---|---|
| src | string | — | An image to smear instead of the drawn print; for WebGL it must be same-origin or CORS. |
| alt | string | — | What the print shows, for assistive technology. |
| brush | number | 56 | The brush's radius in px. |
| relax | number | 2200 | How long the paint takes to remember its shape once you stop, in ms. |
| gloss | number | 0.55 | How wet a fresh smear looks: dry and matte (0) to a sheen that dries as it relaxes (1). |
| strength | number | 1 | How much paint a stroke carries, 0 to 1.5. |
| swirl | number | 0.6 | How much a circling stroke winds the paint into a vortex, 0 to 1. |
| pinned / defaultPinned | boolean | false | Pin every smear so none relax. |
| onPinnedChange | (pinned: boolean) => void | — | Fires when the pin is switched (the P key), with the new state. |
| onSmear | (pinned: boolean) => void | — | Fires as a stroke starts, with whether it is pinned. |
| onRestore | () => void | — | Fires when the print is restored by a double click, Escape or restoreKey. |
| onStateChange | (state: LiquifyPrintState) => void | — | Fires as the print goes between rest, smearing, relaxing and holding. |
| restoreKey | number | 0 | Change it to restore the print from outside. |
| label | string | "Wet print" | Names the print for assistive technology. |
| disabled | boolean | false | Shows the print but takes no input. |
| dpr | number | 2 | Cap on the canvas's device pixel ratio, at most 2. |
| className | string | "h-56 w-full" | Sizes the print; give it a height. |