@pbroom/color-kit/reactPlane renderer
useColorPlaneRenderer
Rasterizes a color plane into a <canvas> you render: every pixel is the plane's color with the two axis channels set to that position.
import { useColorPlaneRenderer } from '@pbroom/color-kit/react';use-color-plane-renderer.ts:153function useColorPlaneRenderer(
plane: ColorPlaneSpec,
options?: UseColorPlaneRendererOptions,
): ColorPlaneRendererHandle;The hook owns no DOM. Attach ref and canvasKey to a canvas, size it with CSS, and the hook keeps its backing store at the CSS size × device pixel ratio × resolutionScale (scaled down at lower quality), redrawing on resize and when the plane changes. It renders with WebGL by default and falls back to a CPU renderer when WebGL is unavailable or its context is lost, returning to WebGL once the context is restored; GPU resources are freed on unmount. Redraws are coalesced to one per animation frame and skipped when nothing that affects the pixels changed (moving along an axis channel does not repaint). With the default source: 'displayed', pixels are mapped into the display gamut and edgeBehavior decides whether out-of-gamut pixels clamp or turn transparent.
Parameters
- plane
ColorPlaneSpec - Color and axes of the plane.
- options?
UseColorPlaneRendererOptionsdefault{} - Rendering options; see
UseColorPlaneRendererOptions.
Returns
ColorPlaneRendererHandleA ColorPlaneRendererHandle to spread onto the canvas.
Throws
- When both axes use the same channel.
Example
import { useColor, useColorPlaneRenderer } from '@pbroom/color-kit/react';
export function Plane() {
const { requested } = useColor({ defaultColor: '#3b82f6' });
const { ref, canvasKey } = useColorPlaneRenderer(
{ color: requested, axes: { x: { channel: 'l' }, y: { channel: 'c' } } },
{ displayGamut: 'srgb', edgeBehavior: 'transparent' },
);
return <canvas ref={ref} key={canvasKey} style={{ width: 240, height: 160 }} />;
}Edge cases
- Use
canvasKeyas the key. A canvas is locked to the first context kind requested from it, so switching between WebGL and the CPU fallback needs a new element. The hook bumpscanvasKeywhen it does; without it as the canvaskey, the fallback cannot paint and the hook warns once. - Destructure the handle. Write
const { ref, canvasKey } = useColorPlaneRenderer(…). Passinghandle.refstraight to JSX makes the React Compiler treat the whole handle as a ref, so readinghandle.rendererduring render is flagged. - Give the canvas a size. The backing store follows the canvas's CSS
size × device pixel ratio ×
resolutionScale(times thequalitymultiplier), and a zero-sized canvas paints nothing. AResizeObserverrepaints on resize. - Context loss. On
webglcontextlostthe plane switches to the CPU renderer on a fresh canvas, and returns to WebGL when the browser restores the context. GPU resources are freed when the canvas unmounts. - Display gamut. Without
displayGamutthe pixels follow the nearest<Color>provider's active gamut, or'display-p3'without one. - Axes must differ. Both axes on the same channel throw.