# Player

A small animation clock for scenes. `usePlayer` ticks `t` (seconds) with `requestAnimationFrame` and gives you play, pause, seek, speed and looping. `PlayerBar` is a ready-made control bar for it.

`Plot2D`, `Plot3D` and `ModelLab` use these internally. Use them directly when you animate something else, such as a CSS demo, a canvas or a custom chart.

Group: Science

## Import

```tsx
import { usePlayer, PlayerBar } from "@indoku/ui"
```

## Anatomy

```text
const player = usePlayer({ duration, loop?, autoPlay?, speed? })
// player.t, player.playing, player.speed, player.duration
// player.play(), pause(), toggle(), seek(t), setSpeed(s)

<PlayerBar player={player} />
```

## Examples

### Clock and control bar

Drive anything from `player.t`. Here a dot moves along a track.

```tsx
function PlayerBasic() {
  const player = usePlayer({ duration: 4, loop: true })
  const pct = (player.t / 4) * 100
  return (
    <div style={{ border: "1px solid var(--indoku-colors-border, #8884)", borderRadius: 8, overflow: "hidden" }}>
      <div style={{ position: "relative", height: 64 }}>
        <div style={{ position: "absolute", top: 20, left: `calc(${pct}% - ${pct * 0.24}px)`, width: 24, height: 24, borderRadius: 12, background: "#3b82f6" }} />
      </div>
      <PlayerBar player={player} />
    </div>
  )
}
```

### Your own controls

`autoPlay: false` starts paused and `loop: false` stops at the end. Build any controls from the returned methods.

```tsx
function PlayerCustom() {
  const player = usePlayer({ duration: 6, loop: false, autoPlay: false })
  return (
    <div style={{ display: "grid", gap: 8 }}>
      <div style={{ fontVariantNumeric: "tabular-nums" }}>
        t = {player.t.toFixed(2)} s · {player.playing ? "playing" : "paused"} · {player.speed}x
      </div>
      <div style={{ display: "flex", gap: 8 }}>
        <button onClick={player.play}>Play</button>
        <button onClick={player.pause}>Pause</button>
        <button onClick={() => player.seek(0)}>Reset</button>
        <button onClick={() => player.setSpeed(2)}>2x</button>
      </div>
    </div>
  )
}
```

## Props

### usePlayer(options)

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `duration` * | `number` |  | Length in seconds. 0 or less means static: the clock never ticks. |
| `loop` | `boolean` | `true` | Wrap around at the end. When false, playback stops at `duration`. |
| `autoPlay` | `boolean` | `true (false with reduced motion)` | Start playing right away. |
| `speed` | `number` | `1` | Initial playback speed multiplier. |

### PlayerBar

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `player` * | `PlayerState` |  | The object returned by `usePlayer`. |

`*` = required. Style props and HTML attributes are accepted too.

## Accessibility

- The bar uses a native `button` and `input[type=range]`, both labeled and keyboard accessible.
- `prefers-reduced-motion` turns autoplay off by default.

## Notes

- `t` is React state updated every frame, so keep components that read it small, or compute from it with `useMemo`.
- Changing `duration` resets the clock to 0.

## See also

- Plot 2D: https://ui.indoku.org/docs/plot-2d
