flag-cloth

React

Canvas sizing, full core options, mutable props, Strict Mode cleanup, and imperative refs.

FlagCloth is a thin wrapper around the framework-independent core. It creates a container and core instance after mount, applies mutable options through setOptions(), and destroys the instance during cleanup.

import { useRef } from 'react';
import {
  FlagCloth,
  type Attachment,
  type FlagClothInstance,
} from 'flag-cloth/react';

const attachment = {
  points: [[0, 0], [0, 8], [0, 16], [0, 24]],
} satisfies Attachment;

export function Banner() {
  const flag = useRef<FlagClothInstance>(null);

  return (
    <FlagCloth
      ref={flag}
      texture="/flag.webp"
      width={3}
      height={2}
      segments={{ x: 40, y: 24 }}
      attachment={attachment}
      canvasWidth="100%"
      canvasHeight={560}
      wind={{ strength: 7, turbulence: 0.35 }}
      interaction={{ enabled: true, dragRadius: 1 }}
      onReady={(instance) => console.log(instance.stats)}
      onError={(error) => console.error(error)}
    />
  );
}

Canvas size versus cloth size

These are separate measurements:

PropsPurpose
width and heightPhysical cloth dimensions in simulation units. They control rest lengths and aspect ratio.
canvasWidth and canvasHeightCSS dimensions of the React-owned canvas container. They accept normal React CSS values such as 720, '100%', '60vh', or 'min(100%, 900px)'.

The canvas fills that container. ResizeObserver updates its CSS viewport and GPU backing store without recreating the simulation. The backing-store resolution is additionally capped by renderer.maxPixelRatio.

You can use className or style instead when layout belongs in CSS:

<FlagCloth
  className="flagViewport"
  style={{ width: '100%', aspectRatio: '3 / 2' }}
  texture="/flag.webp"
/>
.flagViewport {
  width: min(100%, 900px);
  height: clamp(320px, 55vw, 600px);
}

When both are supplied, canvasWidth and canvasHeight override the corresponding style dimensions. The container must resolve to a non-zero width and height before the renderer can draw.

Props

FlagClothProps contains every FlagClothOptions property except the vanilla-only container, plus:

PropTypePurpose
classNamestringClass on the canvas container.
styleCSSPropertiesInline CSS on the canvas container.
canvasWidthCSSProperties['width']Explicit container width.
canvasHeightCSSProperties['height']Explicit container height.
onReady(instance) => voidCalled after the initial texture is ready.
onError(error) => voidReceives initial texture or mutable-update errors.

The full attachment union—including partial edges and custom points—is described in Attachments and pinning. Every other core default is listed in Configuration.

Mutable props

Changes to these props use the existing instance:

  • texture, attachment, wind, simulation, interaction, renderer, material, lighting, camera, visibility, and debug
  • width, height, and segments rebuild cloth topology while preserving the canvas and WebGL2 context
  • canvasWidth, canvasHeight, className, and style resize through normal browser layout and ResizeObserver

advanced and autoStart are construction-time options. The four WebGL2 context attributes—renderer.alpha, antialias, desynchronized, and powerPreference—are also construction-time settings.

Particle positions and the animation loop never enter React state, so cloth animation does not cause React renders. Passing stable nested option objects with useMemo can avoid redundant setOptions() calls in frequently rerendering parents, but it is not required for correctness.

Imperative ref

The forwarded ref is the same FlagClothInstance returned by createFlagCloth():

<button onClick={() => flag.current?.reset()}>Reset</button>
<button onClick={() => flag.current?.pause()}>Pause</button>
<button onClick={() => flag.current?.resume()}>Resume</button>

Use the ref for imperative events. Ordinary configuration should stay in props so React remains the source of truth.

Strict Mode

React Strict Mode's development mount/cleanup/mount cycle is safe. Every core instance owns and removes its animation frame, observers, Pointer Event listeners, GPU resources, optional debug panel, and library-created canvas during cleanup.

On this page