Step 4 - painter

2 min czytania

Create a pure utility module (board.util.ts) - no Angular imports - that owns all geometry and painting. The board component will delegate to it.

  1. drawElement(ctx, el, helpers) rendering every BoardElement type:

    • path: smoothed polyline from points[].
    • note: sticky note, default 180x180, filled rounded rect with a subtle shadow, wrapped centered label.
    • text: multi-line text block honoring fontSize/bold/italic/align.
    • shape: all 10 kinds (rect, roundRect, ellipse, triangle, diamond, hexagon, star, bubble, line, arrow); fillable "area shapes" vs stroke-only lines; arrowheads on 'arrow'.
    • frame: large back-layer container with a title label at the top-left, drawn as a light outline panel.
    • connection: resolved later (prompt 16) - stub it.
    • image: resolved later (prompt 15) - stub it.
  2. orderForDraw(els): stable paint order in three bands - frames at the back, then connections, then everything else. Within a band sort by optional z (missing = 0), ties broken by createdAt. All rendering, hit-testing and exports must consume this order.

  3. Hit-testing: hitTest(els, x, y) returning the topmost element (iterate the draw order backwards); point-in-shape per kind, distance-to-segment for paths and lines with a tolerance scaled by 1/viewport.scale; boundsOf(el) for marquee intersection.

  4. Note label fitting: fitNoteFontSize(ctx, text, w, h) - binary-search the largest font size whose wrapped text fits the note with a 0.12 padding ratio, line-height ratio 1.3, floor at 7px. Memoize results in a Map capped at 2000 entries (clear wholesale when exceeded) - this cache is what keeps repainting hundreds of notes cheap.

  5. Palettes: 8 pastel NOTE_COLORS, a stroke color set, background presets including one dark.

Write vitest specs for fitNoteFontSize and hitTest edge cases (rotated nothing yet - just bands, tolerance, empty text).

Acceptance: a hardcoded demo array of one of each element type renders correctly in draw-order bands, and clicking reports the correct topmost element id.

Dyskusja

Komentarze: 0

Brak komentarzy. Rozpocznij dyskusję.