Shapes
The built-in shapes, the props they share, and the one idea that makes CanvasFlow precise - every shape has real geometry.
The built-in shapes#
type |
What it is | Notable props |
|---|---|---|
geo |
Rectangles, ellipses, diamonds, stars, clouds and 13 more | geo, w, h, text, fill, edges |
text |
Text, auto-sized or with a fixed width | text, autoSize, w, font, fontSize |
note |
A sticky note | text, color |
draw |
Freehand strokes, with pen pressure | points, isPen, isClosed |
highlight |
The highlighter | points |
line |
A line through any number of points | points, arrowKind, closed, line ends |
arrow |
An arrow that can bind to shapes and carry a label | start, mid, end, arrowKind, text |
image |
An image (from a file, the clipboard or a URL) | assetId, w, h, radius |
embed |
YouTube, Vimeo, Figma, CodePen and other embeds | url, w, h |
frame |
A frame that clips and owns the shapes inside it | name, w, h, background |
spec |
A data-driven shape from a plugin (see Plugins) | specId, w, h |
The geo kinds, drawn by the engine itself:
rectangleellipsediamondtrianglepentagonhexagonoctagonstarparallelogramtrapezoidarrow-rightarrow-leftarrow-uparrow-downcloudheartcheck-boxx-boxEvery shape has real geometry#
This is the idea the whole engine rests on. Each shape type has a getGeometry() that returns its true outline: the points of a star, the curve of a hand-drawn ellipse, the stroke of a 1.5 px line, the rounded corners when edges are round.
That one outline is used for everything:
- Hover and click. Clicking inside a star with no fill selects nothing. Clicking its edge selects it.
- The selection outline, which hugs the shape instead of its bounding box.
- The marquee and the lasso, in
touchorcontainmode. - The eraser, which follows the path of your pointer across real strokes.
- Snapping, to edges and centers.
- Arrow bindings, which land on the outline, not on an invisible box.
A live CanvasFlow editor runs here when JavaScript is on.
The hit area is generous where it should be: thin lines get a tolerance that grows for touch and pen, so they're easy to grab, while the outline stays exact.
Props and styles#
Shapes share style props with the same names, which is how one style panel works for every shape:
| Prop | Values |
|---|---|
color |
black, grey, white, red, orange, yellow, green, teal, blue, violet, pink, brown, or any CSS color |
fill |
none, semi, solid, hachure, cross-hatch, dots |
size |
s, m, l, xl (stroke width) |
dash |
solid, dashed, dotted |
sketch |
0, 1, 2 (sloppiness) |
font |
hand, sans, serif, mono |
A shape supports a style when its default props contain that key. When nothing is selected, the panel shows the styles the current tool will use, and new shapes pick them up. More in Styles and themes.
fill: 'none'fill: 'semi'fill: 'solid'fill: 'hachure'fill: 'cross-hatch'fill: 'dots'Working with shapes#
// Create (props you leave out come from the defaults and current styles)
const id = editor.createShape({ type: 'note', x: 0, y: 0, props: { text: 'Ship Friday' } })
// Read
const shape = editor.getShape(id)
const bounds = editor.getShapePageBounds(id)
const geometry = editor.getShapeGeometry(shape!)
// Update and delete
editor.updateShape({ id, rotation: Math.PI / 12, props: { color: 'green' } })
editor.deleteShapes([id])
Frames and groups#
Frames are shapes that own other shapes: drag something into a frame and it becomes a child (its parentId is the frame), clipped to the frame and moved with it.
Groups are not shapes. A group is an id in each member's groupIds. Clicking a grouped shape selects the group; double-click enters it to select inside. Groups nest.
const group = editor.groupShapes(ids)
editor.ungroupShapes(ids)
Unknown shapes are kept#
If a document contains a shape type your app doesn't register (a plugin someone else had, a newer version), CanvasFlow keeps the record and draws a labeled placeholder. Nothing is dropped, and it renders properly again when the type is available.
Next#
- Lines and arrows go deeper on the shapes people draw most.
- Custom shapes shows how to add your own.