Skip to content

feat: polygon tool (#96) - #197

Merged
tbolis merged 9 commits into
release/1.1.0from
feat/polygon
Oct 30, 2026
Merged

tbolis merged 9 commits into
release/1.1.0from
feat/polygon

Conversation

@tbolis

@tbolis tbolis commented Oct 28, 2026

Copy link
Copy Markdown
Owner

Summary

Adds the polygon tool for 1.1.0 (issue #96): tool="polygon", Tools.Polygon, Types.Tool.POLYGON.

  • Each click or tap places a vertex where the pointer is released. A line follows the pointer from the last vertex (on touch, while the finger is down, so the vertex lands where the finger is lifted).
  • A polygon is closed by a click or tap on the first vertex (within 10 pixels, 20 on touch, the first vertex is ringed when the pointer is near enough), by a double click or double tap, or by the Enter key. The Escape key cancels it. It needs three vertices, with fewer the closing gestures do nothing. The keys are listened to on the document only while a polygon is in progress, and not when the focus is in a field to type in.
  • The polygon in progress is drawn on the top canvas only, as the laser pointer is. It is not an object, not in toJSON() or toDataURL(), and not in the undo history. When it is closed it is one fabric.Polygon and one undo step, onObjectAdded is called once with it, and onChange is called once, not for each vertex. onMouseDown and onMouseUp are still called for every click.
  • It takes lineColor, lineWidth and fillColor (transparent by default) as the rectangle does. It is a shape like the others: the select tool moves, scales and rotates it as a whole, the eraser cuts it, and toJSON() and fromJSON() save and load it. The README says how to read its vertices from points.
  • Another tool closes a polygon with three vertices and keeps it, and drops one with fewer. Unmounting drops it.
  • The vertices are in canvas coordinates, and the radii are in screen pixels, so a change of the view of the canvas does not disturb a polygon in progress. zoom() and the resize of the canvas scale the polygon in progress with the objects.
  • Showcase: a Polygon button with a one-line hint, and the full instructions in its tooltip. README: tool table and a section. CHANGELOG: 1.1.0 entry.
  • The tools get three hooks: finish() (called before dispose() when another tool takes over), scale() (called when the sketch scales its objects) and notifiesChange(), which replaces the check of the laser pointer in the events manager. autoresize() returns the factors it scaled by.

Checks

yarn format:check, yarn lint, yarn typecheck and yarn build pass. yarn test: 334 passing and 1 todo, on React 19 and on React 18 (58 tests for the polygon). Changing the code on purpose made the tests fail in each case I tried (the closing gestures, the radius in screen pixels, the eraser mark, the transforms of the select tool, the export, the scaling).

In headless Chrome, driven through the DevTools protocol with real mouse and touch events: the closing gestures, the preview and the ring, Escape and Enter, a polygon closed by touch, the export with a polygon in progress (identical to the export of the empty sketch), a resize of the window in the middle of a polygon, and the hint on one line at every window width from 320 to 1920 pixels.

Not checked: a physical touch device, and browsers other than Chrome.

Notes for review

tool="polygon", Tools.Polygon and Types.Tool.POLYGON (#96). Each click or tap places a vertex where the pointer is released. The polygon is closed by a click or tap on the first vertex, a double click or double tap, or the Enter key, and the Escape key cancels it. The polygon in progress is drawn on the top canvas only, it becomes one fabric.Polygon and one undo step when it is closed.

FabricCanvasTool gets finish(), called before dispose() when another tool takes over, and notifiesChange(), which replaces the check of the laser pointer in the events manager.
… what they do

The eraser cuts the polygon, the cut is saved and undone. The select tool moves, scales and rotates it as a whole, by drags of the mouse. The export has nothing of the polygon in progress, and has the polygon once it is closed.
The vertices are in canvas coordinates, so a zoom or a pan of the view in the middle of a polygon keeps the vertices placed, places the next ones in the new view, draws the preview in it, and keeps the radius of the first vertex in screen pixels.
…nvas

zoom() and the resize of the canvas scale the objects, so they scale the vertices of the polygon in progress too, through the new scale() hook of the tools. autoresize() returns the factors it scaled by.
The visible hint is short enough for the narrowest layout (a container of 228 pixels), and the button has the full instructions as its tooltip.
- The first click after a polygon is closed or cancelled is a vertex, it
  was dropped as the second click of a double click.
- A double click needs the two releases within 4 pixels (10 on touch), so
  two vertices placed quickly near one another do not close the polygon.
- The polygon in progress is dropped when the sketch is cleared, a value is
  loaded, or an undo or a redo is done, through the new reset() hook of the
  tools.
- The keys are taken when the focus is on the page or in the sketch, not on
  a button or a dialog. Of two sketches, the one pressed last takes them.
@tbolis
tbolis merged commit fbf740c into release/1.1.0 Oct 30, 2026
3 checks passed
@tbolis
tbolis deleted the feat/polygon branch October 30, 2026 15:38
@tbolis tbolis mentioned this pull request Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant