# Morph: Playing it

> Spring from one drawing to the next when something changes: MorphIcon in React, mount in the page, motion for any other clock.

Source: https://cesarvenzac.com/morph/docs/playing

When something changes, a press, a state, a route, a drawing can spring to the next source rather than swap. Sent back mid-way, it turns back from where it is, at the speed it was going; sent somewhere new mid-way, it goes on from the frame it's at. `MorphIcon` and `mount` change at once under `prefers-reduced-motion`; with `motion`, call `jump()`.

*Live example on the page: MorphIcon. Real buttons. Press one twice quickly: it turns back from where it is.* Its source:

```tsx
// MorphIcon springs to each new icon. Pressed again mid-way, it
// turns back from where it is, at the speed it was going.
import { MorphIcon } from "@cesarvenzac/morph/react";
import { Pause, Play } from "lucide";

<button onClick={() => setPlaying(!playing)} aria-label={playing ? "Pause" : "Play"}>
  <MorphIcon icon={playing ? Pause : Play} size={20} />
</button>;
```

## In React

```tsx
import { MorphIcon } from "@cesarvenzac/morph/react";
import { Pause, Play } from "lucide";

<button
  onClick={() => setPlaying(!playing)}
  aria-label={playing ? "Pause" : "Play"}
>
  <MorphIcon icon={playing ? Pause : Play} size={20} />
</button>;
```

`MorphIcon` takes an icon or any drawing as `icon`, and its `size` (24 unless said), `strokeWidth` (an icon's, 2 unless said), `spring`, `way`, `extra` and `reducedMotion`; any other prop goes on its `<svg>`. It's hidden from assistive tech unless it's given an `aria-label` or `aria-labelledby`: name the button it's in instead.

`useMorphing(source, options)` is its motion without the `<svg>`, `{ parts, viewBox, motion }`, to draw your own way. They're client components, from React 18 on, which the package takes as an optional peer.

## Without a framework

```typescript
import { mount } from "@cesarvenzac/morph/dom";
import { Menu, X } from "lucide";

const icon = mount(button.querySelector("svg")!, Menu);
let open = false;

button.addEventListener("click", () => {
  open = !open;
  icon.to(open ? X : Menu);
});
```

`mount(svg, source, options)` makes an `<svg>` show `source`: `to(next)` springs there, `set(next)` shows it at once, `stop()` stops it, and `motion` says where it is. It draws with `draw(svg, parts, viewBox)`, a `<path>` a part, made and taken away as their number changes.

## Anywhere else

`motion` is the same spring, pure and immutable, given the time: for Svelte, Vue, a canvas or a game loop.

```typescript
import { motion } from "@cesarvenzac/morph";

let icon = motion(Menu);
icon = icon.toward(X); // when it changes

let last = performance.now();
function tick(now: number) {
  icon = icon.step((now - last) / 1000);
  last = now;
  paint(icon.frame(), icon.viewBox); // yours
  if (!icon.settled) requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
```

`toward(next)` heads for another source, `step(seconds)` moves it along its spring's exact path, the same at any frame rate and after a long pause, `jump()` puts it where it's headed, and `frame()` is what it draws now. It also says its `morph`, `t`, `velocity`, `target`, `source` and `viewBox`, and whether it's `settled`.

## The spring

`spring` is `{ stiffness, damping }`. The default, `PRESS`, is `{ stiffness: 260, damping: 32 }`: as near critically damped as makes no overshoot, so an icon is nearly there in a third of a second, with no wobble. To keep its feel at another pace, divide the stiffness by the square of how many times slower and the damping by that number: four times slower is `{ stiffness: 16.25, damping: 8 }`.

## Driving it yourself

For a morph tied to a slider or a scroll position there's no spring to run: keep the morph, and draw the frame at the `t` you have.

```tsx
const m = useMorph(Sun, Moon);
const t = useScrollProgress(ref); // 0 to 1, yours

return <MorphFrame morph={m} t={t} />;
```

## Morph's docs

- [Overview](https://cesarvenzac.com/morph.md): Morph any SVG into another without the spikes: icons, filled shapes, words, one shape into several.
- [Getting started](https://cesarvenzac.com/morph/docs/getting-started.md): Install Morph, make a morph, and draw any moment of it: in React, in the page, or on a server.
- [What it morphs](https://cesarvenzac.com/morph/docs/sources.md): Icons, any SVG markup, words set in a font, or drawings made by hand: either side can be any of them, and the two needn't match.
- [Shapes and colours](https://cesarvenzac.com/morph/docs/shapes.md): How pieces pair, how holes open and close, what becomes of the shapes one side has more of, and how colours mix.
- [Playing it](https://cesarvenzac.com/morph/docs/playing.md): Spring from one drawing to the next when something changes: MorphIcon in React, mount in the page, motion for any other clock.
- [Ways to morph](https://cesarvenzac.com/morph/docs/ways.md): Soft, even and index, the three ways side by side, the four steps that make soft what it is, and a frame as anchors and handles.
- [API reference](https://cesarvenzac.com/morph/docs/api.md): Every function and type the package exports, entry by entry: the core, React and the DOM.
