refactor: distribute lab-init.js into 34 engine files

lab-init.js: 4098 -> 543 lines (infrastructure + THEORY only)

Each sim's _open*() + UI helpers moved to its engine file:
graph.js, projectile.js, collision.js, magnetic.js, triangle.js,
geometry.js, trigcircle.js, gas.js (molphys), coulomb.js, circuit.js,
reactions.js (chemistry), newton.js (dynamics), chemsandbox.js,
celldivision.js, photosynthesis.js, angrybirds.js, quadratic.js,
normaldist.js, graphtransform.js, pendulum.js, equilibrium.js,
thinlens.js, mirror.js, isoprocess.js, titration.js, refraction.js,
probability.js, bohratom.js, electrolysis.js, waves.js,
crystal.js, orbitals.js, stereo.js, hydrostatics.js

All 34 engine files syntax-checked OK.
This commit is contained in:
Maxim Dolgolyov
2026-05-08 14:54:54 +03:00
parent d5f77bb648
commit ae31e4c4e8
35 changed files with 3657 additions and 3589 deletions
+78 -1
View File
@@ -1,4 +1,4 @@
'use strict';
'use strict';
/* ════════════════════════════════════════════════════════════════
CellDivisionSim v2 — интерактивное деление клетки
Митоз и мейоз · анимация · частицы · скрабинг · клик
@@ -813,3 +813,80 @@ function _cdRRect(ctx, x, y, w, h, r) {
ctx.arcTo(x, y, x + w, y, r);
ctx.closePath();
}
/* ─── lab UI init ─────────────────────────────────── */
function _openCellDivision(mode) {
document.getElementById('sim-topbar-title').textContent = 'Деление клетки';
_simShow('sim-celldivision');
_simShow('ctrl-celldivision');
requestAnimationFrame(() => requestAnimationFrame(() => {
const canvas = document.getElementById('celldiv-canvas');
if (!cellDivSim) {
cellDivSim = new CellDivisionSim(canvas);
cellDivSim.onUpdate = _cdUpdateUI;
}
cellDivSim.fit();
cellDivSim.setMode(mode || 'mitosis');
cellDivSim.start();
_cdBuildDots(cellDivSim._phaseIdx);
// sync auto button state
const autoBtn = document.getElementById('cd-auto-btn');
if (autoBtn) { autoBtn.innerHTML = cellDivSim._autoPlay ? '<svg class="ic" viewBox="0 0 24 24"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg> Пауза' : '<svg class="ic" viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg> Авто'; }
_cdUpdateUI(cellDivSim.info());
}));
}
function _cdBuildDots(activeIdx) {
const box = document.getElementById('cd-phase-dots');
if (!box || !cellDivSim) return;
const phases = cellDivSim._phases();
box.innerHTML = phases.map((p, i) =>
`<div class="cd-phase-dot${i === activeIdx ? ' active' : ''}" onclick="cdJumpPhase(${i})" title="${p.label}"></div>`
).join('');
}
function cdSetMode(mode, btn) {
document.querySelectorAll('.cd-mode-btn').forEach(b => b.classList.remove('active'));
if (btn) btn.classList.add('active');
if (!cellDivSim) return;
cellDivSim.setMode(mode);
_cdBuildDots(cellDivSim._phaseIdx);
_cdUpdateUI(cellDivSim.info());
}
function cdAutoPlay(btn) {
if (!cellDivSim) return;
cellDivSim.toggleAutoPlay();
btn.classList.toggle('active', cellDivSim._autoPlay);
btn.innerHTML = cellDivSim._autoPlay ? '<svg class="ic" viewBox="0 0 24 24"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg> Пауза' : '<svg class="ic" viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg> Авто';
}
function cdPrevPhase() {
if (!cellDivSim) return;
cellDivSim.prevPhase();
_cdBuildDots(cellDivSim._phaseIdx);
}
function cdNextPhase() {
if (!cellDivSim) return;
cellDivSim.nextPhase();
_cdBuildDots(cellDivSim._phaseIdx);
}
function cdJumpPhase(idx) {
if (!cellDivSim) return;
cellDivSim.jumpToPhase(idx);
_cdBuildDots(idx);
}
function _cdUpdateUI(info) {
const v = (id, val) => { const el = document.getElementById(id); if (el) el.textContent = val; };
v('cdbar-v1', info.phase || '—');
v('cdbar-v2', info.chromN || '—');
v('cdbar-v3', info.dna || '—');
v('cdbar-v4', (info.index + 1) + ' / ' + info.total);
v('cdbar-v5', info.mode === 'mitosis' ? 'Митоз' : 'Мейоз');
_cdBuildDots(info.index);
}
/* ── Photosynthesis / Respiration ── */