Web performance: light animation, gestures on a compositor layer, no forced layouts
Deploy web Studio / deploy (push) Successful in 3m46s

Measured with the new tools/bench_web.py on the web Studio's house demo, CPU slowed 6x:

- Idle: running CSS animations repainted the whole drawing every frame (99% of the main
  thread in a window). Animations now step on about ten times a second by default
  ("light", 5% idle); the new toolbar button switches light / smooth / off and the browser
  remembers it; [build] animation sets the default for built pages; view.animation().
  Pan and zoom gestures pause them. Status LEDs pause off-screen and with the rest now.
- Pan 28 -> 10 ms, zoom 69 -> 11 ms per step: gestures move the drawing as one compositor
  layer (transform) and set the viewBox once they end; --iso-k is set on the tags group
  only and only when it changes; the stage box is read once per frame.
- Hover 22 -> 15 ms per move: the tooltip is placed once per frame on its own layer and
  measured only when its text changes; the Studio's x/y readout updates ten times a second
  in a contained box; hover work in the Studio runs once per frame.
- Long object lists skip layout of rows out of sight (content-visibility).
- WASM built with opt-level 3: engine render 11.7 -> 9.4 ms for 10% more download.

Checks: Studio 102/102 (animation modes, pan as a layer, contained readout), web 87/87.
This commit is contained in:
grabowski committed 2026-10-24 20:46:35 +07:00
1 parent 19f4c83ae8
commit a202283a60
15 files changed
+476 -31

No files matched your search

+8
View File
@@ -300,6 +300,14 @@ try:
check(pg.evaluate("() => __studio.S.warnings.length") == 0 and pg.locator('.st-tile[data-type="@room"]').count() == 1,
"it draws without warnings, the palette has the Room tool")
shot(pg, "web-house.jpg")
# low-power default: the pond's fish (and every other animation) step on about ten times a
# second instead of running as CSS animations that repaint the drawing every frame
an = pg.evaluate("""() => { const a = document.querySelector('.iso-svg').getAnimations({subtree: true});
return [__studio.view.animation(), a.length, a.filter(x => x.playState === 'running').length, a.length ? a[0].currentTime : 0]; }""")
pg.wait_for_timeout(500)
t1 = pg.evaluate("() => { const a = document.querySelector('.iso-svg').getAnimations({subtree: true}); return a.length ? a[0].currentTime : 0; }")
check(an[0] == "light" and an[1] >= 6 and an[2] == 0 and t1 > an[3] and pg.locator('.iso-bar [data-a="anim"]').is_visible(),
f"animations are light by default: {an[1]} stepped, none running, time moves on; the toolbar can switch")
# ---------------------------------------------------------------- folder project (OPFS stands in for a picked folder)
demo = {f.relative_to(ROOT / "examples" / "demo").as_posix(): f.read_text(encoding="utf-8")