Ids and frames
Shape ids
ShapeId is a branded string. createShapeId() returns a new UUID v4 from crypto.randomUUID(), which browsers and Node provide natively.
shapeId(value) brands a string you already have, such as an id read from a file or a fixed id in a test. It does not check the string.
GroupId is a second branded string, for the groups a shape belongs to (see The Shape record). createGroupId() returns a UUID v4 and groupId(value) brands a string, exactly like their shape-id counterparts.
createShapeId and createGroupId are the only impure functions in the package. Every other function receives ids as input, so the rest of the package stays deterministic.
Frames
A Frame is the rotated rectangle that holds a shape’s content:
type Frame = { readonly x: number; readonly y: number; readonly width: number; readonly height: number; readonly rotation: Radians;};(x, y)is the top-left corner before rotation, in page space.rotationturns the frame about its centre.widthandheightare never negative. A flip is applied to the content and is not stored on the frame.
Local and page space
Local space has its origin at the frame’s unrotated top-left corner, with axes along the frame’s edges. A frame’s local point (width, height) is its bottom-right corner.
| Function | Result |
|---|---|
frameCenter(frame) |
The centre of the frame, in page space |
frameToPage(frame) |
The Mat that maps local points to page points |
localToPage(frame, p) |
A LocalPoint converted to a PagePoint |
pageToLocal(frame, p) |
A PagePoint converted to a LocalPoint; the inverse of localToPage |
frameCorners(frame) |
The four corners in page space: top-left, top-right, bottom-right, bottom-left |
frameBounds(frame) |
The axis-aligned page Box around the rotated frame |
import { frameBounds, localPoint, localToPage, pageToLocal, radians } from "@draw/shapes";import type { Box, Frame, LocalPoint, PagePoint } from "@draw/shapes";
const frame: Frame = { x: 0, y: 0, width: 100, height: 50, rotation: radians(Math.PI / 2) };
export const topLeftOnPage: PagePoint = localToPage(frame, localPoint(0, 0));
export const backToLocal: LocalPoint = pageToLocal(frame, topLeftOnPage);
export const pageBounds: Box = frameBounds(frame);The frame above is 100 by 50 and turned a quarter turn about its centre (50, 25). Its local top-left lands at (75, -25) on the page, and its page bounds are the 50 by 100 box from (25, -25) to (75, 75).