Skip to content

chore(renderer): pixel-snap at animation end + frame-time budgeting overlay #37

@LeslieOA

Description

@LeslieOA

Summary

Two small renderer hygiene items from the zoom-rendering audit (Workspace CC). Bundled because they're both low-effort infrastructure.

What the audit found

Item 6 — No pixel-grid snap at animation end

Lerped float values mean the final frame can land at fractional coords (e.g. tx = 142.371). Raster content (images, edges, shadows) may render slightly blurry until the next user interaction snaps things. Vector content (text, shapes) is unaffected.

Item 8 — No frame-time budgeting

If a single frame takes >16.6ms (or >8.3ms on ProMotion 120Hz), the animation drops frames. There's no instrumentation to detect or mitigate. On a canvas with 200+ nodes, the live re-render may exceed budget on macOS where culling is currently off.

Proposed fix shapes

Item 6

At t >= 1 in animateCamera's tick:

const pixelRatio = PixelRatio.get();
translateX.value = Math.round(translateX.value * pixelRatio) / pixelRatio;
translateY.value = Math.round(translateY.value * pixelRatio) / pixelRatio;

Cosmetic but visible on retina displays at certain zooms.

Item 8

Debug-build perf overlay that:

  • Measures frame time during animations via performance.now() deltas in the tick function
  • Surfaces a small overlay (FPS, last-frame ms, dropped-frame count) when a devFlag is on
  • Logs warnings when a single frame exceeds budget

If we see frequent budget overruns, that's evidence for the changes in the perf companion issue (Picture overlay during animation + viewport culling on macOS).

Acceptance criteria

  • Pixel snap applied at the end of every animateCamera run
  • Verified on a retina display: post-animation raster content (images, drop shadows) renders crisp
  • Frame-time measurement added to animateCamera's tick
  • Debug overlay gated by a devFlags.ts entry (consistent with existing dev-flag pattern)
  • No production impact — overlay and measurement compiled out in release builds (or no-ops behind __DEV__)

Notes

Item 6 is XS (~5 lines). Item 8 is S (overlay component + flag wiring).

Refs

Surfaced during the zoom-rendering improvements audit (Workspace CC).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions