# Morph: Shapes and colours

> How pieces pair, how holes open and close, what becomes of the shapes one side has more of, and how colours mix.

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

## Pieces

A drawing is pieces. Each subpath of a stroked part is a stroke, and each filled outline, with the holes directly inside it, is an island, found as SVG's fill rule finds them. Pieces are paired across the two sides by their shape (its size, place and turn set aside), by how far apart they are and by how their sizes differ, the pairing that costs least overall: a circle near a circle becomes it, rather than turning into a bar.

A stroke pairs with a fill only when nothing fits better, and one then crossfades into the other as it moves.

## Holes

An island's holes are paired among themselves and move with it. A hole with no partner opens from a point, or closes into one, where it is: the counter of an “o” shrinks away inside the letter as it becomes an “l”, rather than flying off.

## One side has more

`extra` says what becomes of the pieces one side has more of:

- `"auto"`, the default: small pieces lying along a much bigger one join it, as three dots become a line or a loader's rays a circle; the rest gather.
- `"split"`: every extra piece joins the nearest piece of its kind on the other side, so one shape splits into several, or several merge into one. A stroke is shared out between them, a stretch each; a filled shape is cut into parts, one each, about as big as each, so a heart breaks into the letters of a word. A stroke paired with a fill would only crossfade, so they part when either has a piece of its kind to join: letters becoming a sun merge into its disc while its rays grow.
- `"gather"`: each extra piece gathers into a dot as the morph goes on, or grows from one.

A filled shape with holes, or one that won't cut cleanly, isn't cut: each piece becomes the whole of it, the copies fading as they land. A piece with nothing of its kind on the other side gathers whatever `extra` says. And `"index"` pairs commands in order, so it takes no `extra`.

```typescript
// The triangle divides into the two bars.
morph(play, pause, { extra: "split" });
```

*Live example on the page: One side has more. The same pair three ways. Play to pause is where split shines, dots to a line where auto joins them.* Its source:

```tsx
// What becomes of the pieces one side has more of: the same pair,
// three ways, on one clock.
morph(play, pause, { extra: "auto" }); // the default
morph(play, pause, { extra: "split" }); // divide, or merge
morph(play, pause, { extra: "gather" }); // grow from dots, or shrink
```

## Colours

Colours mix in OKLab, alpha premultiplied, as CSS's `color-mix()` mixes them, so a red becoming a blue passes through a clear purple, between the two in lightness, not the dark one an sRGB mix gives. Colours CSS names without a page, hex, `rgb()`, `hsl()` and the named colours, are mixed by Morph into hex. Anything else (the current colour, a CSS variable, `oklch()`) is mixed by the browser: the part's colour is then a `color-mix(in oklab, …)`, which SVG's paint attributes take.

Opacity and stroke widths are interpolated, and caps and joins are the nearer side's.

## Parts

A frame of drawings is parts of `{ d, width, fill, color?, opacity?, cap?, join? }`: `width` the stroke's width in the canvas's units (0 for a fill), and `fill` how filled it is, from 0, a stroke, to 1, a fill, between while one becomes the other. `color` and `opacity` are left out for the current colour and full opacity. A frame of two icons is simpler, `{ d, width }`, each a stroke in the current colour.

`attributesOf` turns a part into a `<path>`'s attributes, the same set every frame, so nothing is left over from the last. Fill with the even-odd rule, as it does: an island's holes are in its path data.

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

attributesOf(m.at(0.5)[0]);
// { d: "M12 3.6C…", fill: "#f0a35c", stroke: "none",
//   "fill-opacity": "1", "fill-rule": "evenodd", … }
```

## 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.
