# Transforms

> Save, restore, translate, rotate and scale the drawing. Rotated and scaled primitives stay exact, and stroke widths scale with them.

Source: https://pixi-silk.schmooky.dev/docs/transforms/

Live demo `transforms` (source):

```ts
import { SilkGraphics } from 'pixi-silk';
import { defineDemo } from './runtime';

// save / translateTransform / rotateTransform / scaleTransform / restore, like Pixi's GraphicsContext.
export default defineDemo({
    size: [420, 220],
    controls: {
        speed: { type: 'range', label: 'speed', min: 0, max: 3, step: 0.05, value: 1 },
    },
    setup({ stage, params, tick }) {
        const g = new SilkGraphics();
        let a = 0;

        stage.addChild(g);
        tick((_t, dt) => {
            a += dt * params.speed;
            g.clear();
            g.save().translateTransform(210, 110);
            for (let i = 0; i < 12; i++) {
                g.save()
                    .rotateTransform((i / 12) * Math.PI * 2 + a)
                    .translateTransform(70, 0)
                    .scaleTransform(0.6 + 0.4 * Math.sin(a * 2 + i));
                // rotated rects stay exact: rotation is part of the primitive, not a tessellation
                g.roundRect(-14, -8, 28, 16, 8).fill(i % 2 ? 0xff9f0a : 0x5e5ce6);
                g.restore();
            }
            g.star(0, 0, 6, 34, 16, -a, 4).fill(0xffd60a);
            g.restore();
        });
    },
});
```

`SilkGraphics` has the same transform stack as Pixi's `GraphicsContext`:

```ts
g.save()
    .translateTransform(210, 110)
    .rotateTransform(Math.PI / 4)
    .scaleTransform(1.5);
g.roundRect(-20, -10, 40, 20, 8).fill(0xff9f0a);   // drawn in the transformed space
g.restore();
```

| method | |
|---|---|
| `save()` / `restore()` | push / pop the current transform |
| `translateTransform(x, y = x)` | move |
| `rotateTransform(angle)` | rotate (radians) |
| `scaleTransform(x, y = x)` | scale |
| `setTransform(a, b, c, d, tx, ty)` | replace with a matrix |
| `resetTransform()` | back to identity |

Silk stores shapes already transformed. Rects, ellipses, hearts and polygons carry their rotation
into the shader. A rotated rounded rect is still an exact distance field, not a tessellation.
Stroke widths, dash lengths and blur radii scale with the transform's uniform scale.

## When to use a Container instead

Transforms bake into the primitives, which suits icons and repeated parts drawn every frame. For
objects that move as a whole (a card sliding in), put them in their own `SilkGraphics` or
`Container`. Then animate `position`, `rotation` or `scale`, which changes one matrix instead of
rebuilding primitives.
