perf(stereo3d): Фаза 0 — render-on-demand, остановка фонового рендера, dispose

- lab-init: _pauseAllSims() паузит активный rAF-сим при переключении (раньше стерео рендерило невидимый canvas вечно)
- stereo: render-on-demand через _invalidate()/_needsRender, loop засыпает и просыпается по взаимодействию
- pointer/touch-слушатели перенесены с window на canvas (pointer-capture), трекаются и снимаются в dispose()
- обработка webglcontextlost/restored + метод dispose()
- _clearGroup стал рекурсивным (устранена утечка вложенных групп), a11y-атрибуты на canvas
- bump stereo.js?v=3

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-05-30 11:05:35 +03:00
parent ed97b6d90b
commit 8af85961b5
4 changed files with 206 additions and 27 deletions
+44
View File
@@ -49,11 +49,55 @@
/* ── sim routing ── */
// Pause all animation-loop sims (non-destructive). Called when switching
// between sims so a previously opened sim doesn't keep rendering offscreen.
function _pauseAllSims() {
if (pSim) pSim.pause();
if (cSim) cSim.pause();
if (gasSim) gasSim.stop();
if (brownSim) brownSim.stop();
if (statesSim) statesSim.stop();
if (diffSim) diffSim.stop();
if (cirSim) cirSim.stop();
if (reacSim) reacSim.stop();
if (flaskSim) flaskSim.stop();
if (rdxSim) rdxSim.stop();
if (ioxSim) ioxSim.stop();
if (newtonSim) newtonSim.stop();
if (sandboxSim && sandboxSim.stop) sandboxSim.stop();
if (crystalSim) crystalSim.stop();
if (orbitalsSim) orbitalsSim.stop();
if (stereoSim) stereoSim.stop();
if (chemSandSim) chemSandSim.stop();
if (cellDivSim) cellDivSim.stop();
if (photosynSim) photosynSim.stop();
if (angryBirdsSim) angryBirdsSim.stop();
if (trigSim) trigSim.stop();
if (pendSim) pendSim.stop();
if (eqSim) eqSim.stop();
if (titrSim) titrSim.stop();
if (probSim) probSim.stop();
if (bohrSim) bohrSim.stop();
if (elecSim) elecSim.stop();
if (wavesSim) wavesSim.stop();
if (radioactiveSim) radioactiveSim.stop();
if (heSim) heSim.stop();
if (qualSim) qualSim.stop();
if (periodicSim) periodicSim.stop();
if (organicSim) organicSim.stop();
if (_solutionsSim) _solutionsSim.stop();
if (mirrorSim && mirrorSim._playing) mirrorSim._stopAnim();
if (mirrorSim && mirrorSim._photonRaf) mirrorSim._stopPhotons();
}
function openSim(id) {
if (_disabledSimIds.has(id.split(':')[0])) return;
document.getElementById('lab-home').style.display = 'none';
document.getElementById('lab-sim').classList.add('open');
// pause whatever sim was running before we switch to the new one
_pauseAllSims();
// hide all inner bodies + controls
ALL_SIM_BODIES.forEach(bid => document.getElementById(bid).style.display = 'none');
ALL_CTRL_BARS.forEach(bid => document.getElementById(bid).style.display = 'none');