feat(labs): механика V2 — 4 ключевые симы школьной физики расширены
pendulum V2 (472 → 1651 строк): - Математический (default, сохранён) - Двойной маятник (Lagrangian RK4, ghost-копия для демо хаоса) - Связанные маятники (биения, чарт θ₁/θ₂) - Пружинный (вертикальный/горизонтальный, T=2π√(m/k)) - Физический (4 формы: стержень/обруч/диск/прямоугольник, с моментом инерции) - Маятник Фуко (Кориолис, slider широты, период прецессии) - Резонанс (внешняя F₀·cos(ω_d·t), резонансная кривая A(ω)) - Фазовый портрет (универсальный toggle для всех режимов) collision V2 (~1000 → 2416 строк): - 1D (default, сохранён) - 2D под углом (импульс по осям, slider e, до/после стат) - Multi-ball (N=2-10, стены с отскоками, перемешать) - Бильярдный стол (6 луз, кий с прицелом, треугольник шаров, реалистичное трение) - Реф.фрейм ЦМ (universal toggle) newton V2 (1693 → 2585 строк): - 4-й закон-таб «Классические задачи» - Машина Атвуда (a=(m₂-m₁)g/(m₁+m₂), идеальный/массивный блок) - Тело на наклонной плоскости (FBD, статика/скольжение, slider α/μ/F_app) - Скатывание шара/цилиндра/обруча (момент инерции, гонка, наглядно почему обруч медленнее) projectile V2 (1900 → 2400 строк): - Парашют: F_d = ½C_d·ρ·A·v² с терминальной скоростью v_t = √(2mg/(C_d·ρ·A)) - C_d selector: парашют/куб/сфера/полусфера/диск; раскрытие парашюта на заданной высоте - Горка-катапульта: v_0 = √(2gL(sinα-μcosα)) автомат - 10 планет: Земля/Луна/Марс/Юпитер/Меркурий/Венера/Сатурн/Уран/Нептун/Плутон с реальными g + плотностью атмосферы (для drag) - Сравнительный режим: 3 планеты одновременно с разными цветами Все 4 симы — additive, существующая функциональность сохранена. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+353
-30
@@ -141,7 +141,7 @@
|
||||
<button class="zoom-btn" id="coll-play-btn" onclick="collPlayPause()" title="Запустить">
|
||||
<svg viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"/></svg>
|
||||
</button>
|
||||
<button class="zoom-btn" onclick="cSim && cSim.reset()" title="Сброс">
|
||||
<button class="zoom-btn" onclick="var _as=_activeSim&&_activeSim();if(_as)_as.reset();_collSyncBtn();" title="Сброс">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
@@ -237,6 +237,10 @@
|
||||
<button class="zoom-btn nscene-btn active" id="nscn-A" onclick="newtonScene('A',this)" style="font-size:.65rem;font-weight:800">A</button>
|
||||
<button class="zoom-btn nscene-btn" id="nscn-B" onclick="newtonScene('B',this)" style="font-size:.65rem;font-weight:800">B</button>
|
||||
<button class="zoom-btn nscene-btn" id="nscn-C" onclick="newtonScene('C',this)" style="font-size:.65rem;font-weight:800">C</button>
|
||||
<!-- classic scenes (law 4, hidden by default) -->
|
||||
<button class="zoom-btn nscene-btn cl-scene-btn" id="nscn-cl-atwood" data-scene="atwood" onclick="classicScene('atwood')" style="display:none;font-size:.6rem;font-weight:800">Атвуд</button>
|
||||
<button class="zoom-btn nscene-btn cl-scene-btn" id="nscn-cl-ramp" data-scene="ramp" onclick="classicScene('ramp')" style="display:none;font-size:.6rem;font-weight:800">Наклон</button>
|
||||
<button class="zoom-btn nscene-btn cl-scene-btn" id="nscn-cl-roll" data-scene="roll" onclick="classicScene('roll')" style="display:none;font-size:.6rem;font-weight:800">Качение</button>
|
||||
<div style="width:1px;height:20px;background:rgba(255,255,255,0.15);margin:0 3px"></div>
|
||||
<button class="zoom-btn" id="newton-action-top" onclick="newtonAction()" style="font-size:.65rem;font-weight:800;font-family:Manrope,sans-serif"><svg class="ic" viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg> Действие</button>
|
||||
</span>
|
||||
@@ -1499,19 +1503,84 @@
|
||||
<button class="mag-mode-btn dyn-mode" id="dyn-mode-law1" onclick="dynMode('law1',this)" style="flex:1;font-size:.68rem;padding:5px 0">I закон</button>
|
||||
<button class="mag-mode-btn dyn-mode" id="dyn-mode-law2" onclick="dynMode('law2',this)" style="flex:1;font-size:.68rem;padding:5px 0">II закон</button>
|
||||
<button class="mag-mode-btn dyn-mode" id="dyn-mode-law3" onclick="dynMode('law3',this)" style="flex:1;font-size:.68rem;padding:5px 0">III закон</button>
|
||||
<button class="mag-mode-btn dyn-mode" id="dyn-mode-law4" onclick="dynMode('law4',this)" style="flex:1;font-size:.68rem;padding:5px 0">Классич.</button>
|
||||
</div>
|
||||
|
||||
<!-- ══ Newton controls (shown in law modes) ══ -->
|
||||
<div id="dyn-newton-panel" style="display:none">
|
||||
|
||||
<!-- Scene selector -->
|
||||
<div class="gp-section-title" style="margin-bottom:8px">Сцена</div>
|
||||
<!-- Scene selector (standard A/B/C — hidden for law 4) -->
|
||||
<div class="gp-section-title" style="margin-bottom:8px" id="newton-scene-title">Сцена</div>
|
||||
<div style="display:flex;gap:5px;margin-bottom:12px" id="newton-scene-row">
|
||||
<button class="mag-mode-btn nscene-btn active" id="nscn-panel-A" onclick="newtonScene('A',null,this)" style="flex:1;font-size:.72rem">A</button>
|
||||
<button class="mag-mode-btn nscene-btn" id="nscn-panel-B" onclick="newtonScene('B',null,this)" style="flex:1;font-size:.72rem">B</button>
|
||||
<button class="mag-mode-btn nscene-btn" id="nscn-panel-C" onclick="newtonScene('C',null,this)" style="flex:1;font-size:.72rem">C</button>
|
||||
</div>
|
||||
|
||||
<!-- Classic scene selector (law 4 only) -->
|
||||
<div id="newton-classic-panel" style="display:none">
|
||||
<div style="display:flex;gap:5px;margin-bottom:10px">
|
||||
<button class="mag-mode-btn cl-scene-btn active" id="nscn-panel-cl-atwood" data-scene="atwood" onclick="classicScene('atwood')" style="flex:1;font-size:.68rem">Атвуд</button>
|
||||
<button class="mag-mode-btn cl-scene-btn" id="nscn-panel-cl-ramp" data-scene="ramp" onclick="classicScene('ramp')" style="flex:1;font-size:.68rem">Наклон</button>
|
||||
<button class="mag-mode-btn cl-scene-btn" id="nscn-panel-cl-roll" data-scene="roll" onclick="classicScene('roll')" style="flex:1;font-size:.68rem">Качение</button>
|
||||
</div>
|
||||
|
||||
<!-- Atwood sub-panel -->
|
||||
<div id="cl-sub-atwood">
|
||||
<div class="param-block">
|
||||
<div class="param-header"><span class="param-name">m₁ (кг)</span><span class="param-val" id="atw-m1-val">5 кг</span></div>
|
||||
<input type="range" class="param-slider" id="sl-atw-m1" min="1" max="20" value="5" oninput="atwM1Change()">
|
||||
</div>
|
||||
<div class="param-block">
|
||||
<div class="param-header"><span class="param-name">m₂ (кг)</span><span class="param-val" id="atw-m2-val">8 кг</span></div>
|
||||
<input type="range" class="param-slider" id="sl-atw-m2" min="1" max="20" value="8" oninput="atwM2Change()">
|
||||
</div>
|
||||
<div class="gp-section-title" style="margin:4px 0">Блок</div>
|
||||
<div style="display:flex;gap:5px;margin-bottom:8px">
|
||||
<button class="mag-mode-btn atw-massive-btn active" data-val="false" onclick="atwMassiveToggle(false)" style="flex:1;font-size:.68rem">Идеальный</button>
|
||||
<button class="mag-mode-btn atw-massive-btn" data-val="true" onclick="atwMassiveToggle(true)" style="flex:1;font-size:.68rem">Массивный</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Ramp sub-panel -->
|
||||
<div id="cl-sub-ramp" style="display:none">
|
||||
<div class="param-block">
|
||||
<div class="param-header"><span class="param-name">Угол α</span><span class="param-val" id="ramp-alpha-val">30°</span></div>
|
||||
<input type="range" class="param-slider" id="sl-ramp-alpha" min="1" max="89" value="30" oninput="rampAlphaChange()">
|
||||
</div>
|
||||
<div class="param-block">
|
||||
<div class="param-header"><span class="param-name">Масса m (кг)</span><span class="param-val" id="newton-m1-ramp-val">5 кг</span></div>
|
||||
<input type="range" class="param-slider" id="sl-ramp-mass" min="1" max="20" value="5" oninput="rampMassChange()">
|
||||
</div>
|
||||
<div class="param-block">
|
||||
<div class="param-header"><span class="param-name">Коэфф. трения μ</span><span class="param-val" id="ramp-mu-val">0.20</span></div>
|
||||
<input type="range" class="param-slider" id="sl-ramp-mu" min="0" max="1.5" step="0.01" value="0.20" oninput="rampMuChange()">
|
||||
</div>
|
||||
<div class="param-block">
|
||||
<div class="param-header"><span class="param-name">Внеш. сила F (Н)</span><span class="param-val" id="ramp-force-val">0 Н</span></div>
|
||||
<input type="range" class="param-slider" id="sl-ramp-force" min="0" max="80" value="0" oninput="rampForceChange()">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Roll sub-panel -->
|
||||
<div id="cl-sub-roll" style="display:none">
|
||||
<div class="param-block">
|
||||
<div class="param-header"><span class="param-name">Угол α</span><span class="param-val" id="roll-alpha-val">20°</span></div>
|
||||
<input type="range" class="param-slider" id="sl-roll-alpha" min="5" max="60" value="20" oninput="rollAlphaChange()">
|
||||
</div>
|
||||
<div class="gp-section-title" style="margin:4px 0">Режим</div>
|
||||
<div style="display:flex;gap:5px;margin-bottom:8px">
|
||||
<button class="mag-mode-btn roll-friction-btn active" data-val="false" onclick="rollFrictionToggle(false)" style="flex:1;font-size:.68rem">Качение</button>
|
||||
<button class="mag-mode-btn roll-friction-btn" data-val="true" onclick="rollFrictionToggle(true)" style="flex:1;font-size:.68rem">+Трение</button>
|
||||
</div>
|
||||
<div style="font-size:0.68rem;color:var(--text-3);line-height:1.5;padding:4px 6px;background:rgba(255,255,255,0.03);border-radius:6px;border:1px solid var(--border);margin-bottom:6px">
|
||||
Шар: a = (5/7)g·sinα<br>
|
||||
Цилиндр: a = (2/3)g·sinα<br>
|
||||
Обруч: a = (1/2)g·sinα
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /#newton-classic-panel -->
|
||||
|
||||
<!-- Scene description -->
|
||||
<div id="newton-scene-desc" style="font-size:0.71rem;color:var(--text-3);line-height:1.6;margin-bottom:10px;padding:6px 8px;background:rgba(255,255,255,0.03);border-radius:8px;border:1px solid var(--border)">
|
||||
Закон инерции: тело движется равномерно при отсутствии сил.
|
||||
@@ -1777,6 +1846,117 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Parachute -->
|
||||
<div class="gp-section-title" style="margin-top:6px">Парашют</div>
|
||||
<label class="tri-layer-row" id="chute-row" onclick="projToggleParachute(this)" style="margin-bottom:6px">
|
||||
<span class="tri-dot" style="background:rgba(6,214,224,0.5)"></span>
|
||||
<span class="tri-layer-name">Парашют</span>
|
||||
<span class="tri-toggle" id="chute-toggle" style="background:rgba(255,255,255,0.12)"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:2px;transition:margin-left .15s"></span></span>
|
||||
</label>
|
||||
<div id="chute-params" style="display:none">
|
||||
<div class="param-block">
|
||||
<div class="param-header">
|
||||
<span class="param-name">Площадь A</span>
|
||||
<span class="param-val" id="p-chute-area">1.0 м²</span>
|
||||
</div>
|
||||
<input type="range" class="param-slider" id="sl-chute-area" min="1" max="100" value="10" oninput="projChuteAreaChange()">
|
||||
</div>
|
||||
<div class="param-block" style="margin-bottom:6px">
|
||||
<span class="param-name" style="font-size:.68rem">Форма (Cd)</span>
|
||||
<select id="sel-chute-cd" onchange="projChuteCdChange()" style="width:100%;margin-top:4px;background:#0d0d2a;color:#fff;border:1px solid rgba(255,255,255,.15);border-radius:6px;padding:4px 6px;font-size:.75rem">
|
||||
<option value="1.5" selected>Парашют (1.5)</option>
|
||||
<option value="1.05">Куб (1.05)</option>
|
||||
<option value="0.47">Сфера (0.47)</option>
|
||||
<option value="0.42">Полусфера (0.42)</option>
|
||||
<option value="1.17">Плоский диск (1.17)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="param-block">
|
||||
<div class="param-header">
|
||||
<span class="param-name">Раскрыть на h</span>
|
||||
<span class="param-val" id="p-chute-height">Сразу</span>
|
||||
</div>
|
||||
<input type="range" class="param-slider" id="sl-chute-height" min="0" max="100" value="0" oninput="projChuteHeightChange()">
|
||||
<div style="font-size:.6rem;color:var(--text-3);margin-top:2px">0 = немедленно, >0 = раскрыть на этой высоте</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Ramp -->
|
||||
<div class="gp-section-title" style="margin-top:6px">Наклонная горка</div>
|
||||
<label class="tri-layer-row" id="ramp-row" onclick="projToggleRamp(this)" style="margin-bottom:6px">
|
||||
<span class="tri-dot" style="background:rgba(255,180,50,0.5)"></span>
|
||||
<span class="tri-layer-name">Старт с горки</span>
|
||||
<span class="tri-toggle" id="ramp-toggle" style="background:rgba(255,255,255,0.12)"><span style="display:block;width:12px;height:12px;border-radius:50%;background:#fff;margin:2px;margin-left:2px;transition:margin-left .15s"></span></span>
|
||||
</label>
|
||||
<div id="ramp-params" style="display:none">
|
||||
<div class="param-block">
|
||||
<div class="param-header">
|
||||
<span class="param-name">Угол горки α</span>
|
||||
<span class="param-val" id="p-ramp-angle">30°</span>
|
||||
</div>
|
||||
<input type="range" class="param-slider" id="sl-ramp-angle" min="5" max="85" value="30" oninput="projRampChange()">
|
||||
</div>
|
||||
<div class="param-block">
|
||||
<div class="param-header">
|
||||
<span class="param-name">Длина L</span>
|
||||
<span class="param-val" id="p-ramp-length">10 м</span>
|
||||
</div>
|
||||
<input type="range" class="param-slider" id="sl-ramp-length" min="1" max="50" value="10" oninput="projRampChange()">
|
||||
</div>
|
||||
<div class="param-block">
|
||||
<div class="param-header">
|
||||
<span class="param-name">Трение μ</span>
|
||||
<span class="param-val" id="p-ramp-mu">0.10</span>
|
||||
</div>
|
||||
<input type="range" class="param-slider" id="sl-ramp-mu" min="0" max="80" value="10" oninput="projRampChange()">
|
||||
<div style="font-size:.6rem;color:var(--text-3);margin-top:2px">v = sqrt(2gL(sinα − μ cosα))</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Planet -->
|
||||
<div class="gp-section-title" style="margin-top:6px">Планета / гравитация</div>
|
||||
<div class="param-block" style="margin-bottom:6px">
|
||||
<select id="sel-planet" onchange="projPlanetChange()" style="width:100%;background:#0d0d2a;color:#fff;border:1px solid rgba(255,255,255,.15);border-radius:6px;padding:4px 6px;font-size:.75rem">
|
||||
<option value="earth" selected>Земля — g=9.81</option>
|
||||
<option value="moon">Луна — g=1.62</option>
|
||||
<option value="mars">Марс — g=3.71</option>
|
||||
<option value="venus">Венера — g=8.87</option>
|
||||
<option value="jupiter">Юпитер — g=24.79</option>
|
||||
<option value="mercury">Меркурий — g=3.7</option>
|
||||
<option value="saturn">Сатурн — g=10.44</option>
|
||||
<option value="uranus">Уран — g=8.69</option>
|
||||
<option value="neptune">Нептун — g=11.15</option>
|
||||
<option value="pluto">Плутон — g=0.62</option>
|
||||
</select>
|
||||
</div>
|
||||
<button id="proj-planet-compare-btn" class="proj-preset-chip" onclick="projTogglePlanetCompare()" style="width:100%;text-align:left;display:flex;align-items:center;gap:6px;margin-bottom:4px">
|
||||
<svg class="ic" viewBox="0 0 24 24"><circle cx="5" cy="12" r="3"/><circle cx="12" cy="5" r="3"/><circle cx="19" cy="19" r="3"/><line x1="5" y1="12" x2="12" y2="5"/><line x1="12" y1="5" x2="19" y2="19"/></svg>
|
||||
<span>Сравн.планет: Выкл</span>
|
||||
</button>
|
||||
<div id="proj-planet-compare-panel" style="display:none;font-size:.65rem;color:rgba(255,255,255,.6);margin-bottom:4px">
|
||||
<div style="display:flex;gap:4px;flex-direction:column">
|
||||
<div style="display:flex;align-items:center;gap:6px">
|
||||
<span style="color:#06D6E0;font-weight:700">1:</span>
|
||||
<select onchange="projPlanetCompareChange(0,this.value)" style="flex:1;background:#0d0d2a;color:#06D6E0;border:1px solid rgba(6,214,224,.3);border-radius:4px;padding:2px 4px;font-size:.7rem">
|
||||
<option value="earth" selected>Земля</option><option value="moon">Луна</option><option value="mars">Марс</option><option value="venus">Венера</option><option value="jupiter">Юпитер</option><option value="mercury">Меркурий</option><option value="saturn">Сатурн</option><option value="uranus">Уран</option><option value="neptune">Нептун</option><option value="pluto">Плутон</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="display:flex;align-items:center;gap:6px">
|
||||
<span style="color:#7BF5A4;font-weight:700">2:</span>
|
||||
<select onchange="projPlanetCompareChange(1,this.value)" style="flex:1;background:#0d0d2a;color:#7BF5A4;border:1px solid rgba(123,245,164,.3);border-radius:4px;padding:2px 4px;font-size:.7rem">
|
||||
<option value="earth">Земля</option><option value="moon" selected>Луна</option><option value="mars">Марс</option><option value="venus">Венера</option><option value="jupiter">Юпитер</option><option value="mercury">Меркурий</option><option value="saturn">Сатурн</option><option value="uranus">Уран</option><option value="neptune">Нептун</option><option value="pluto">Плутон</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="display:flex;align-items:center;gap:6px">
|
||||
<span style="color:#F15BB5;font-weight:700">3:</span>
|
||||
<select onchange="projPlanetCompareChange(2,this.value)" style="flex:1;background:#0d0d2a;color:#F15BB5;border:1px solid rgba(241,91,181,.3);border-radius:4px;padding:2px 4px;font-size:.7rem">
|
||||
<option value="earth">Земля</option><option value="moon">Луна</option><option value="mars" selected>Марс</option><option value="venus">Венера</option><option value="jupiter">Юпитер</option><option value="mercury">Меркурий</option><option value="saturn">Сатурн</option><option value="uranus">Уран</option><option value="neptune">Нептун</option><option value="pluto">Плутон</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="gp-section-title" style="margin-top:6px">Пресеты</div>
|
||||
<div style="display:flex;flex-wrap:wrap;gap:6px">
|
||||
<button class="proj-preset-chip" onclick="projPreset(20,45,0,9.81)">Земля 45°</button>
|
||||
@@ -2017,7 +2197,7 @@
|
||||
</svg>
|
||||
<span id="coll-launch-label">Запустить</span>
|
||||
</button>
|
||||
<button class="proj-reset-btn" onclick="cSim && cSim.reset(); _collSyncBtn()">
|
||||
<button class="proj-reset-btn" onclick="var _rs=_activeSim&&_activeSim();if(_rs)_rs.reset();_collSyncBtn()">
|
||||
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.2">
|
||||
<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/>
|
||||
</svg>
|
||||
@@ -2444,44 +2624,187 @@
|
||||
|
||||
<!-- ── PENDULUM sim body ── -->
|
||||
<div id="sim-pendulum" class="sim-proj-wrap" style="display:none">
|
||||
<!-- mode bar -->
|
||||
<div style="display:flex;gap:4px;padding:6px 12px;background:rgba(22,22,38,0.8);flex-wrap:wrap;border-bottom:1px solid rgba(255,255,255,0.07)">
|
||||
<button class="pend-mode-btn active" data-mode="math" onclick="pendSetMode('math')" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(255,255,255,0.15);background:rgba(155,93,229,0.2);color:#ccc;cursor:pointer">Математ.</button>
|
||||
<button class="pend-mode-btn" data-mode="double" onclick="pendSetMode('double')" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">Двойной</button>
|
||||
<button class="pend-mode-btn" data-mode="coupled" onclick="pendSetMode('coupled')" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">Связанные</button>
|
||||
<button class="pend-mode-btn" data-mode="spring" onclick="pendSetMode('spring')" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">Пружинный</button>
|
||||
<button class="pend-mode-btn" data-mode="physical" onclick="pendSetMode('physical')" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">Физич.</button>
|
||||
<button class="pend-mode-btn" data-mode="foucault" onclick="pendSetMode('foucault')" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">Фуко</button>
|
||||
<button class="pend-mode-btn" data-mode="resonance" onclick="pendSetMode('resonance')" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">Резонанс</button>
|
||||
<button id="btn-pend-phase" onclick="pendTogglePhase()" style="font-size:.72rem;padding:3px 10px;border-radius:14px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer;margin-left:auto">Фаз. портрет</button>
|
||||
</div>
|
||||
<div class="sim-body-wrap">
|
||||
<div class="proj-panel" style="width:220px;gap:0">
|
||||
<div class="gp-section-title" style="margin-bottom:8px">Параметры</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:55px">θ = <span id="pend-theta-val" style="color:var(--violet);font-weight:700">45</span>°</label>
|
||||
<input type="range" id="sl-pend-theta" min="5" max="170" step="1" value="45" oninput="pendParam('theta',this.value)" style="flex:1">
|
||||
<div class="proj-panel" style="width:230px;gap:0;overflow-y:auto;max-height:100%">
|
||||
|
||||
<!-- MATH params -->
|
||||
<div class="pend-params" data-mode="math">
|
||||
<div class="gp-section-title" style="margin-bottom:8px">Математич. маятник</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:55px">θ = <span id="pend-theta-val" style="color:var(--violet);font-weight:700">45</span>°</label>
|
||||
<input type="range" id="sl-pend-theta" min="5" max="170" step="1" value="45" oninput="pendParam('theta',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:55px">L = <span id="pend-L-val" style="color:var(--cyan);font-weight:700">200</span></label>
|
||||
<input type="range" id="sl-pend-L" min="60" max="300" step="5" value="200" oninput="pendParam('L',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:55px">g = <span id="pend-g-val" style="color:#FFD166;font-weight:700">9.81</span></label>
|
||||
<input type="range" id="sl-pend-g" min="1" max="25" step="0.1" value="9.81" oninput="pendParam('g',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:70px">Затух. <span id="pend-damp-val" style="color:#EF476F;font-weight:700">0</span></label>
|
||||
<input type="range" id="sl-pend-damp" min="0" max="2" step="0.05" value="0" oninput="pendParam('damping',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="gp-section-title" style="margin-bottom:6px;margin-top:8px">Пресеты</div>
|
||||
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px">
|
||||
<button class="preset-btn" onclick="pendPreset(45,200,9.81,0)">Земля</button>
|
||||
<button class="preset-btn" onclick="pendPreset(45,200,1.62,0)">Луна</button>
|
||||
<button class="preset-btn" onclick="pendPreset(170,200,9.81,0)">Большой θ</button>
|
||||
<button class="preset-btn" onclick="pendPreset(45,200,9.81,0.5)">Затухание</button>
|
||||
</div>
|
||||
<div class="pp-hint">Тащи грузик мышью для установки угла</div>
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:55px">L = <span id="pend-L-val" style="color:var(--cyan);font-weight:700">200</span></label>
|
||||
<input type="range" id="sl-pend-L" min="60" max="300" step="5" value="200" oninput="pendParam('L',this.value)" style="flex:1">
|
||||
|
||||
<!-- DOUBLE params -->
|
||||
<div class="pend-params" data-mode="double" style="display:none">
|
||||
<div class="gp-section-title" style="margin-bottom:8px">Двойной маятник</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:65px">L1 = <span id="pend-d-L1-val" style="color:var(--cyan);font-weight:700">130</span></label>
|
||||
<input type="range" min="50" max="200" step="5" value="130" oninput="pendDoubleParam('L1',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:65px">L2 = <span id="pend-d-L2-val" style="color:var(--cyan);font-weight:700">100</span></label>
|
||||
<input type="range" min="50" max="200" step="5" value="100" oninput="pendDoubleParam('L2',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:65px">m1 = <span id="pend-d-m1-val" style="color:#FFD166;font-weight:700">1.5</span></label>
|
||||
<input type="range" min="0.5" max="4" step="0.1" value="1.5" oninput="pendDoubleParam('m1',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:65px">m2 = <span id="pend-d-m2-val" style="color:#FFD166;font-weight:700">1.0</span></label>
|
||||
<input type="range" min="0.5" max="4" step="0.1" value="1.0" oninput="pendDoubleParam('m2',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:65px">θ1 = <span id="pend-d-th1-val" style="color:var(--violet);font-weight:700">108</span>°</label>
|
||||
<input type="range" min="10" max="170" step="1" value="108" oninput="pendDoubleParam('th1',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:65px">θ2 = <span id="pend-d-th2-val" style="color:var(--violet);font-weight:700">72</span>°</label>
|
||||
<input type="range" min="10" max="170" step="1" value="72" oninput="pendDoubleParam('th2',this.value)" style="flex:1">
|
||||
</div>
|
||||
<button id="btn-pend-ghost" onclick="pendToggleGhost()" style="width:100%;margin-top:6px;font-size:.75rem;padding:5px;border-radius:8px;border:1px solid rgba(239,71,111,0.4);background:rgba(239,71,111,0.1);color:#EF476F;cursor:pointer">Сравнить траектории (хаос)</button>
|
||||
<div class="pp-hint" style="margin-top:6px">Чувствительность к нач. условиям (+0.001 рад)</div>
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:55px">g = <span id="pend-g-val" style="color:#FFD166;font-weight:700">9.81</span></label>
|
||||
<input type="range" id="sl-pend-g" min="1" max="25" step="0.1" value="9.81" oninput="pendParam('g',this.value)" style="flex:1">
|
||||
|
||||
<!-- COUPLED params -->
|
||||
<div class="pend-params" data-mode="coupled" style="display:none">
|
||||
<div class="gp-section-title" style="margin-bottom:8px">Связанные маятники</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:65px">L = <span id="pend-cp-L-val" style="color:var(--cyan);font-weight:700">160</span></label>
|
||||
<input type="range" min="80" max="260" step="5" value="160" oninput="pendCoupledParam('L',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:65px">k = <span id="pend-cp-k-val" style="color:#FFD166;font-weight:700">0.30</span></label>
|
||||
<input type="range" min="0.01" max="2" step="0.01" value="0.3" oninput="pendCoupledParam('k',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:65px">θ1 = <span id="pend-cp-th1-val" style="color:var(--violet);font-weight:700">36</span>°</label>
|
||||
<input type="range" min="5" max="90" step="1" value="36" oninput="pendCoupledParam('th1',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="pp-hint">θ2=0: энергия перекачивается от маятника 1 к маятнику 2 и обратно</div>
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:70px">Затух. <span id="pend-damp-val" style="color:#EF476F;font-weight:700">0</span></label>
|
||||
<input type="range" id="sl-pend-damp" min="0" max="2" step="0.05" value="0" oninput="pendParam('damping',this.value)" style="flex:1">
|
||||
|
||||
<!-- SPRING params -->
|
||||
<div class="pend-params" data-mode="spring" style="display:none">
|
||||
<div class="gp-section-title" style="margin-bottom:8px">Пружинный маятник</div>
|
||||
<div style="display:flex;gap:4px;margin-bottom:10px">
|
||||
<button class="sp-mode-btn active" data-m="vert" onclick="pendSpringMode('vert')" style="flex:1;font-size:.72rem;padding:4px;border-radius:8px;border:1px solid rgba(255,255,255,0.15);background:rgba(6,214,224,0.15);color:#06D6E0;cursor:pointer">Вертик.</button>
|
||||
<button class="sp-mode-btn" data-m="horiz" onclick="pendSpringMode('horiz')" style="flex:1;font-size:.72rem;padding:4px;border-radius:8px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">Горизонт.</button>
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:65px">k = <span id="pend-sp-k-val" style="color:#FFD166;font-weight:700">20</span></label>
|
||||
<input type="range" min="1" max="100" step="1" value="20" oninput="pendSpringParam('k',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:65px">m = <span id="pend-sp-m-val" style="color:var(--violet);font-weight:700">1</span> кг</label>
|
||||
<input type="range" min="0.1" max="5" step="0.1" value="1" oninput="pendSpringParam('m',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:65px">x0 = <span id="pend-sp-x0-val" style="color:#EF476F;font-weight:700">8</span> см</label>
|
||||
<input type="range" min="1" max="20" step="0.5" value="8" oninput="pendSpringParam('x0',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="pp-hint">T = 2π√(m/k) не зависит от g (горизонт.)</div>
|
||||
</div>
|
||||
<div style="margin-top:8px"></div>
|
||||
<div class="gp-section-title" style="margin-bottom:6px">Пресеты</div>
|
||||
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px">
|
||||
<button class="preset-btn" onclick="pendPreset(45,200,9.81,0)">Земля</button>
|
||||
<button class="preset-btn" onclick="pendPreset(45,200,1.62,0)">Луна</button>
|
||||
<button class="preset-btn" onclick="pendPreset(170,200,9.81,0)">Большой θ</button>
|
||||
<button class="preset-btn" onclick="pendPreset(45,200,9.81,0.5)">Затухание</button>
|
||||
|
||||
<!-- PHYSICAL params -->
|
||||
<div class="pend-params" data-mode="physical" style="display:none">
|
||||
<div class="gp-section-title" style="margin-bottom:8px">Физический маятник</div>
|
||||
<div style="display:flex;flex-wrap:wrap;gap:3px;margin-bottom:10px">
|
||||
<button class="ph-shape-btn active" data-s="rod" onclick="pendPhysShape('rod')" style="font-size:.72rem;padding:3px 8px;border-radius:8px;border:1px solid rgba(155,93,229,0.4);background:rgba(155,93,229,0.15);color:#9B5DE5;cursor:pointer">Стержень</button>
|
||||
<button class="ph-shape-btn" data-s="hoop" onclick="pendPhysShape('hoop')" style="font-size:.72rem;padding:3px 8px;border-radius:8px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">Обруч</button>
|
||||
<button class="ph-shape-btn" data-s="disk" onclick="pendPhysShape('disk')" style="font-size:.72rem;padding:3px 8px;border-radius:8px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">Диск</button>
|
||||
<button class="ph-shape-btn" data-s="rect" onclick="pendPhysShape('rect')" style="font-size:.72rem;padding:3px 8px;border-radius:8px;border:1px solid rgba(255,255,255,0.15);background:rgba(22,22,38,0.6);color:#ccc;cursor:pointer">Прямоуг.</button>
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:65px">L = <span id="pend-ph-L-val" style="color:var(--cyan);font-weight:700">200</span></label>
|
||||
<input type="range" min="60" max="260" step="5" value="200" oninput="pendPhysParam('L',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:65px">θ = <span id="pend-ph-theta-val" style="color:var(--violet);font-weight:700">36</span>°</label>
|
||||
<input type="range" min="5" max="120" step="1" value="36" oninput="pendPhysParam('theta',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:65px">Затух. <span id="pend-ph-damping-val" style="color:#EF476F;font-weight:700">0</span></label>
|
||||
<input type="range" min="0" max="1" step="0.02" value="0" oninput="pendPhysParam('damping',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="pp-hint">T зависит от момента инерции I и расст. до ц.т. d</div>
|
||||
</div>
|
||||
<div class="pp-hint">Тащи грузик мышью для установки угла</div>
|
||||
|
||||
<!-- FOUCAULT params -->
|
||||
<div class="pend-params" data-mode="foucault" style="display:none">
|
||||
<div class="gp-section-title" style="margin-bottom:8px">Маятник Фуко</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:65px">φ = <span id="pend-fc-phi-val" style="color:#FFD166;font-weight:700">45</span>°</label>
|
||||
<input type="range" min="1" max="90" step="1" value="45" oninput="pendFoucaultParam('phi',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="pp-hint">Вид сверху. Плоскость качаний вращаетс�; из-за вращения Земли. T = 24 ч / sin(φ)</div>
|
||||
<div class="pp-hint" style="color:#FFD166;margin-top:4px">Полюс (90°): оборот за 24 ч. Экватор: почти не вращается.</div>
|
||||
</div>
|
||||
|
||||
<!-- RESONANCE params -->
|
||||
<div class="pend-params" data-mode="resonance" style="display:none">
|
||||
<div class="gp-section-title" style="margin-bottom:8px">Резонанс</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:70px">ω = <span id="pend-rs-dOmega-val" style="color:#EF476F;font-weight:700">1.50</span></label>
|
||||
<input type="range" min="0.1" max="6" step="0.05" value="1.5" oninput="pendResonanceParam('dOmega',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:70px">F0 = <span id="pend-rs-F0-val" style="color:#FFD166;font-weight:700">0.80</span></label>
|
||||
<input type="range" min="0.1" max="3" step="0.05" value="0.8" oninput="pendResonanceParam('F0',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:70px">γ = <span id="pend-rs-gamma-val" style="color:var(--cyan);font-weight:700">0.30</span></label>
|
||||
<input type="range" min="0.01" max="2" step="0.01" value="0.3" oninput="pendResonanceParam('gamma',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="proj-slider-row" style="margin-bottom:8px">
|
||||
<label style="font-size:.78rem;color:#ccc;width:70px">L = <span id="pend-rs-L-val" style="color:var(--violet);font-weight:700">180</span></label>
|
||||
<input type="range" min="60" max="300" step="5" value="180" oninput="pendResonanceParam('L',this.value)" style="flex:1">
|
||||
</div>
|
||||
<div class="pp-hint">Красная стрелка — вынуждающая сила. Пик при ω ≈ ω₀.</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="proj-canvas-outer">
|
||||
<canvas id="pendulum-canvas"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="proj-stats-bar" id="pendbar">
|
||||
<div class="pstat"><div class="pstat-label">Угол</div><div class="pstat-val" id="pendbar-v1" style="color:var(--violet)">45°</div></div>
|
||||
<div class="pstat"><div class="pstat-label">ω</div><div class="pstat-val" id="pendbar-v2" style="color:var(--cyan)">0</div></div>
|
||||
<div class="pstat"><div class="pstat-label">Период T</div><div class="pstat-val" id="pendbar-v3" style="color:#FFD166">—</div></div>
|
||||
<div class="pstat"><div class="pstat-label">Энергия</div><div class="pstat-val" id="pendbar-v4" style="color:#EF476F">—</div></div>
|
||||
<div class="pstat"><div class="pstat-label">Угол / коорд.</div><div class="pstat-val" id="pendbar-v1" style="color:var(--violet)">45°</div></div>
|
||||
<div class="pstat"><div class="pstat-label">ω</div><div class="pstat-val" id="pendbar-v2" style="color:var(--cyan)">0</div></div>
|
||||
<div class="pstat"><div class="pstat-label">Период T</div><div class="pstat-val" id="pendbar-v3" style="color:#FFD166">—</div></div>
|
||||
<div class="pstat"><div class="pstat-label">Режим</div><div class="pstat-val" id="pendbar-v4" style="color:#EF476F">—</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user