Skip to main content

Shape Transforms

Every element carries its own affine transform: position (local-space origin), rotation (radians, counter-clockwise), and scale (a Vec2). The shape is rotated and scaled around its position.

Updating a transformโ€‹

Transforms are plain fields, so you move, rotate, or scale through updateElement. moveElement is a shorthand for setting position.

import { moveElement, updateElement } from "@oh-just-another/scene";
import { elementId } from "@oh-just-another/types";

// Translate
let { scene: s } = moveElement(scene, elementId("r1"), { x: 120, y: 80 });

// Rotate 45ยฐ and scale 2ร— horizontally
({ scene: s } = updateElement(s, elementId("r1"), (el) => ({
...el,
rotation: Math.PI / 4,
scale: { x: 2, y: el.scale.y },
})));

Local vs world boundsโ€‹

getElementLocalBounds returns the untransformed box (via the shape's registered bounder). getElementWorldBounds applies position / rotation / scale and returns the conservative axis-aligned bounding box of the transformed corners โ€” the form used for spatial-index keys.

import { getElementLocalBounds, getElementWorldBounds, getElement } from "@oh-just-another/scene";
import { elementId } from "@oh-just-another/types";

const el = getElement(scene, elementId("r1"));
if (el) {
const local = getElementLocalBounds(el);
const world = getElementWorldBounds(el);
}

Resize constraintsโ€‹

Optional minWidth / minHeight / maxWidth / maxHeight clamp interactive resize, and noFlip prevents dragging a handle through the opposite edge.