Editor has no Bezier handles on smooth/symmetric nodes — user can only drag the node itself, no way to adjust the curve's control handles (Illustrator-style handles are the standard for vector editing) #251

Open
opened 2026-10-04 03:35:00 +00:00 by Mark · 0 comments
Owner

Finding

src/components/editor/canvasRenderer.ts doesn't reference handleIn or handleOut. grep -n 'handleIn\|handleOut' src/components/editor/canvasRenderer.ts returns 0.

A user draws a smooth path:

  • Clicks the "Smooth" node type (per #219 fix)
  • The node renders as a circle (per #219)
  • There's no visible control handle from the node to the curve

Vector editors (Illustrator, Figma, Inkscape) all show two short lines from a smooth node — the "handles" — that the user can drag to adjust the curve. The handles determine how the curve enters and exits the node.

A user trying to make an S-curve with a smooth node:

  • Places a node at the start
  • Switches to Smooth type
  • The node is now smooth
  • The line from the previous node enters with some default tangent
  • The user can't adjust the tangent
  • Has to add more smooth nodes to approximate the curve

This is a fundamental limitation of the editor's curve model. Smooth nodes should have handles.

Where

  • canvasRenderer: src/components/editor/canvasRenderer.ts (no handles)
  • PathNode type: src/components/editor/types.ts (need to check if handleIn/handleOut fields exist)
  • No handle drag: grep -n 'handleIn' src/ returns 0

Suggested fix shape

  1. Add handleIn: Point | null and handleOut: Point | null to the PathNode type:
export interface PathNode {
  id: string;
  x: number;
  y: number;
  type: 'corner' | 'smooth' | 'symmetric';
  handleIn?: Point | null;  // null for corner nodes
  handleOut?: Point | null; // null for corner nodes
}
  1. In canvasRenderer, for smooth/symmetric nodes, draw the two handle lines from the node to the handleIn/handleOut points, with small handle circles at the ends.

  2. In the editor's pointer handler, allow dragging a handle to update its position. The handle's mirror: for symmetric nodes, dragging handleIn also moves handleOut (mirrored). For smooth nodes, the two handles can be moved independently.

  3. Keyboard handling: when a handle is selected (e.g., via clicking on it), Delete/Backspace removes it (turns the node into a corner).

  4. EditorContextMenu (per #191): add "Reset Handles" item to recenter handles at default positions.

The math: a cubic Bezier between two smooth nodes has handles at both ends. The "smooth" type means the two handles are collinear with the node. The "symmetric" type means they're equal length and opposite.

Severity

Medium. Smooth nodes are limited without handle control. Users who want precise curves can't get them.

Discovered by

Gap analysis (2026-10-02) of editor curve editing.

  • #211 (open) — Editor has no Bezier-handle numeric input. Same family; the input is the polish on top of the drag.
  • #219 (open) — Node visual differentiation. The handles are the visual for smooth/symmetric nodes.
  • Most vector editors show handles; the editor's current model is closer to a polyline than a Bezier curve.
## Finding `src/components/editor/canvasRenderer.ts` doesn't reference `handleIn` or `handleOut`. `grep -n 'handleIn\|handleOut' src/components/editor/canvasRenderer.ts` returns 0. A user draws a smooth path: - Clicks the "Smooth" node type (per #219 fix) - The node renders as a circle (per #219) - There's no visible control handle from the node to the curve Vector editors (Illustrator, Figma, Inkscape) all show two short lines from a smooth node — the "handles" — that the user can drag to adjust the curve. The handles determine how the curve enters and exits the node. A user trying to make an S-curve with a smooth node: - Places a node at the start - Switches to Smooth type - The node is now smooth - The line from the previous node enters with some default tangent - The user can't adjust the tangent - Has to add more smooth nodes to approximate the curve This is a fundamental limitation of the editor's curve model. Smooth nodes should have handles. ## Where - canvasRenderer: `src/components/editor/canvasRenderer.ts` (no handles) - PathNode type: `src/components/editor/types.ts` (need to check if handleIn/handleOut fields exist) - No handle drag: `grep -n 'handleIn' src/` returns 0 ## Suggested fix shape 1. **Add `handleIn: Point | null` and `handleOut: Point | null` to the `PathNode` type**: ```ts export interface PathNode { id: string; x: number; y: number; type: 'corner' | 'smooth' | 'symmetric'; handleIn?: Point | null; // null for corner nodes handleOut?: Point | null; // null for corner nodes } ``` 2. **In canvasRenderer**, for smooth/symmetric nodes, draw the two handle lines from the node to the handleIn/handleOut points, with small handle circles at the ends. 3. **In the editor's pointer handler**, allow dragging a handle to update its position. The handle's mirror: for symmetric nodes, dragging handleIn also moves handleOut (mirrored). For smooth nodes, the two handles can be moved independently. 4. **Keyboard handling**: when a handle is selected (e.g., via clicking on it), Delete/Backspace removes it (turns the node into a corner). 5. **EditorContextMenu** (per #191): add "Reset Handles" item to recenter handles at default positions. The math: a cubic Bezier between two smooth nodes has handles at both ends. The "smooth" type means the two handles are collinear with the node. The "symmetric" type means they're equal length and opposite. ## Severity Medium. Smooth nodes are limited without handle control. Users who want precise curves can't get them. ## Discovered by Gap analysis (2026-10-02) of editor curve editing. ## Related - #211 (open) — Editor has no Bezier-handle numeric input. Same family; the input is the polish on top of the drag. - #219 (open) — Node visual differentiation. The handles are the visual for smooth/symmetric nodes. - Most vector editors show handles; the editor's current model is closer to a polyline than a Bezier curve.
Sign in to join this conversation.
No description provided.