Step 6 - Selection, move, resize

1 min read

Implement selection and direct manipulation on the select tool. State: selectedIds: string[] signal, with derived selectedId (exactly one) and multiSelected.

Selection:

  • Click selects the topmost hit element; click on empty space clears.
  • Marquee: drag on empty space draws a rubber-band rect; select every element whose bounds intersect it. A sweep of <= 3 world units counts as a plain click, not a marquee.
  • Shift-click toggles membership; elements sharing a groupId always toggle together.
  • Ctrl/Cmd+A selects all non-connection, non-locked elements.
  • Draw selection on the canvas: dashed world-space outline per selected element.

Move:

drag any selected element to move the whole selection. Record per-element drag origins in a Map on pointerdown and apply deltas from the origin (never incremental deltas - they drift). Elements with locked=true can be selected but never moved, resized or erased.

Resize:

only when exactly ONE element is selected:

  • 8 handles (nw n ne e se s sw w) drawn in screen-constant size; per-handle CSS cursors; hover state switches the cursor before pointerdown.
  • Boxes resize normally with per-type minimum sizes (frames/containers min 60 world units).
  • 'path' elements scale their points[] proportionally into the new bounds.
  • 'text' elements scale fontSize on corner handles only.
  • Lines/arrows get endpoint dragging instead of handles: hit-test both endpoints and drag one while the other stays anchored.

Acceptance: single and multi drag feel correct at any zoom, resize respects minimums and per-type behavior, shift-click grouping works, marquee vs click threshold behaves, locked elements refuse to move.

Discussion

0 comments

No comments yet. Start the discussion.