Skip to content

Canvas view changes trigger a full engine round-trip per frame during pan/zoom #707

Description

@bpowers

Problem

Every canvas view change runs a full engine round-trip. Canvas.tsx calls onViewBoxChange on:

  • every wheel event,
  • every momentum-animation requestAnimationFrame frame, and
  • every pinch update.

Editor.queueViewUpdate then awaits, per event:

  • engine.applyPatch (upsertView),
  • engine.serializeProtobuf,
  • a full serializeJson, and
  • a projectFromJson re-parse of the entire project.

So a single pan or pinch gesture fires this entire serialize/re-parse pipeline on every animation frame.

Why it matters

On large models this makes panning/zooming jankier than necessary and burns WASM CPU. View changes are purely presentational, so doing full project serialization + re-parse per frame is wasted work in the interactive hot path -- a developer-experience and performance concern.

Components affected

  • src/diagram (Canvas.tsx, Editor.tsx -- queueViewUpdate)
  • src/engine (WASM applyPatch / serializeProtobuf / serializeJson / projectFromJson)

Context

Identified during the frontend-react-audit branch review (June 2026). As of that branch, these view-only updates no longer pollute the undo history (the worst user-visible symptom has been fixed), but the per-frame persistence work remains.

Suggested fix

Debounce/coalesce view persistence: only push the final viewBox to the engine on gesture end or after ~250ms idle, while keeping the optimistic local view state immediate so the canvas stays responsive.

Metadata

Metadata

Assignees

No one assigned

    Labels

    frontendInvolved the React-based Typescript frontend

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions