feat(phys10 ch5 wave2): §29 «Сила Ампера» + §30 «Сила Лоренца» + 3D-траектория
This commit is contained in:
@@ -1407,34 +1407,715 @@ function build_p28(){
|
||||
function build_p29(){
|
||||
const box = document.getElementById('p29-body');
|
||||
let html = '';
|
||||
|
||||
/* THEORY 1 — Сила Ампера */
|
||||
html += makeCard('theory', "Сила Ампера", "§29", `
|
||||
<p><b>Сила Ампера</b> — этот параграф в разработке (Phase 1+).</p>
|
||||
<p>Здесь появятся: теория, формулы, разобранные примеры и 3–4 интерактива в стиле «алгебры 11» — таблицы, симуляции, ползунки, drag-and-drop и автопроверяемые тренажёры.</p>
|
||||
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.92rem">
|
||||
<b>Phase 0:</b> создан скелет учебника. <b>Phase 5+:</b> наполнение этого § содержанием по учебнику «Физика 10» (Беларусь, 2019).
|
||||
</p>
|
||||
<p><b>Сила Ампера</b> — сила, действующая на проводник с током, помещённый в магнитное поле.</p>
|
||||
<p style="margin-top:8px"><b>Модуль</b>:</p>
|
||||
<p style="text-align:center;margin:8px 0">$$F_A = B I L \\sin\\alpha$$</p>
|
||||
<ul style="margin:6px 0 6px 22px">
|
||||
<li>$B$ — индукция магнитного поля (Тл),</li>
|
||||
<li>$I$ — сила тока в проводнике (А),</li>
|
||||
<li>$L$ — длина участка проводника в поле (м),</li>
|
||||
<li>$\\alpha$ — угол между направлением тока и вектором $\\vec{B}$.</li>
|
||||
</ul>
|
||||
<p style="margin-top:10px"><b>Особые случаи:</b></p>
|
||||
<ul style="margin:6px 0 6px 22px">
|
||||
<li>$\\alpha = 90°$ (ток $\\perp \\vec{B}$): $F_{max} = B I L$ — максимум.</li>
|
||||
<li>$\\alpha = 0°$ или $180°$ (ток $\\parallel \\vec{B}$): $F_A = 0$ — сила отсутствует.</li>
|
||||
</ul>
|
||||
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px"><b>Главная мысль.</b> Магнитное поле действует на ток. Чем сильнее поле, длиннее провод, больше ток и удачнее ориентация (ближе к $90°$), тем больше сила.</p>
|
||||
`);
|
||||
|
||||
/* THEORY 2 — Правило левой руки */
|
||||
html += makeCard('rule', "Правило левой руки", "§29", `
|
||||
<p><b>Правило левой руки</b> — приём для определения направления силы Ампера.</p>
|
||||
<p style="margin-top:8px">Расположи <b>левую руку</b> так, чтобы:</p>
|
||||
<ol style="margin:6px 0 6px 22px">
|
||||
<li>Линии магнитной индукции $\\vec{B}$ <b>входили в ладонь</b> (поле «прокалывало» ладонь).</li>
|
||||
<li>Четыре <b>выпрямленных пальца</b> показывали направление <b>тока</b> $I$.</li>
|
||||
<li>Тогда отогнутый под $90°$ <b>большой палец</b> покажет направление <b>силы Ампера</b> $\\vec{F_A}$.</li>
|
||||
</ol>
|
||||
<p style="margin-top:10px"><b>Свойство.</b> Сила Ампера $\\vec{F_A}$ всегда <b>перпендикулярна</b> и проводнику с током, и вектору $\\vec{B}$.</p>
|
||||
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px"><b>Важно.</b> Это же правило (с заменой «тока» на «скорость положительного заряда») работает для силы Лоренца (§30). Для отрицательного заряда направление противоположное.</p>
|
||||
`);
|
||||
|
||||
/* THEORY 3 — Применение */
|
||||
html += makeCard('example', "Где работает сила Ампера", "§29", `
|
||||
<p><b>Электродвигатель.</b> В магнитном поле находится рамка с током. Силы Ампера, действующие на её стороны, создают <b>вращающий момент</b>. Рамка вращается — получается механическое движение из электрического тока. От детских игрушек до электровозов и промышленных приводов — везде это устройство.</p>
|
||||
<p style="margin-top:10px"><b>Электроизмерительные приборы.</b> В <b>гальванометре</b> рамка с током отклоняется в поле постоянного магнита; угол отклонения пропорционален силе тока, и стрелка показывает его на шкале.</p>
|
||||
<p style="margin-top:10px"><b>Громкоговоритель.</b> Переменный ток в катушке, помещённой в поле постоянного магнита, заставляет мембрану колебаться в такт со звуковым сигналом — рождаются звуковые волны.</p>
|
||||
<p style="margin-top:10px"><b>Магнитная левитация.</b> Токи в катушках поездов на магнитной подвеске (маглев) создают поля, которые отталкивают сверхпроводящие или ферромагнитные элементы пути — поезд буквально парит над рельсами.</p>
|
||||
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px"><b>Принцип суперпозиции для $\\vec{B}$.</b> Магнитное поле от нескольких источников равно <b>векторной сумме</b> полей от каждого. Поэтому сложные конфигурации (катушки, рамки, провода) разбиваются на простые и складываются.</p>
|
||||
`);
|
||||
|
||||
/* INTERACTIVE 1 — Правило левой руки (визуализатор) */
|
||||
html += `<div class="wg" id="p29-iv1">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Правило левой руки: куда направлена $\\vec{F_A}$?</div></div>
|
||||
<div class="wg-help">Магнитное поле $\\vec{B}$ направлено <b>в экран</b> (×). Выбери направление тока и параметры — увидишь силу Ампера.</div>
|
||||
<div style="display:flex;gap:8px;justify-content:center;margin-bottom:10px;flex-wrap:wrap">
|
||||
<button class="btn primary" id="p29-iv1-up" data-d="up">Ток вверх ↑</button>
|
||||
<button class="btn" id="p29-iv1-dn" data-d="dn">Ток вниз ↓</button>
|
||||
<button class="btn" id="p29-iv1-rt" data-d="rt">Ток вправо →</button>
|
||||
<button class="btn" id="p29-iv1-lt" data-d="lt">Ток влево ←</button>
|
||||
</div>
|
||||
<div class="sliders">
|
||||
<label>$I$: <b id="p29-iv1-IL">5.0</b> А <input type="range" id="p29-iv1-I" min="0" max="10" value="5" step="0.1"></label>
|
||||
<label>$B$: <b id="p29-iv1-BL">1.0</b> Тл <input type="range" id="p29-iv1-B" min="0" max="2" value="1" step="0.05"></label>
|
||||
</div>
|
||||
<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:8px">
|
||||
<svg id="p29-iv1-svg" viewBox="0 0 480 320" width="100%" style="height:auto"></svg>
|
||||
</div>
|
||||
<div id="p29-iv1-out" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.94rem;line-height:1.65;text-align:center"></div>
|
||||
</div>`;
|
||||
|
||||
/* INTERACTIVE 2 — Калькулятор */
|
||||
html += `<div class="wg" id="p29-iv2">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Калькулятор силы Ампера</div></div>
|
||||
<div class="wg-help">Введи параметры — получи $F_A = B I L \\sin\\alpha$ в Ньютонах.</div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:10px">
|
||||
<label style="display:flex;flex-direction:column;gap:4px;font-size:.92rem">$B$ (Тл):<input type="number" id="p29-iv2-B" value="0.5" step="0.01" style="padding:7px;border:1px solid var(--border);border-radius:6px"></label>
|
||||
<label style="display:flex;flex-direction:column;gap:4px;font-size:.92rem">$I$ (А):<input type="number" id="p29-iv2-I" value="2" step="0.1" style="padding:7px;border:1px solid var(--border);border-radius:6px"></label>
|
||||
<label style="display:flex;flex-direction:column;gap:4px;font-size:.92rem">$L$ (м):<input type="number" id="p29-iv2-L" value="0.1" step="0.01" style="padding:7px;border:1px solid var(--border);border-radius:6px"></label>
|
||||
<label style="display:flex;flex-direction:column;gap:4px;font-size:.92rem">$\\alpha$ (°):<input type="number" id="p29-iv2-A" value="90" step="1" min="0" max="180" style="padding:7px;border:1px solid var(--border);border-radius:6px"></label>
|
||||
</div>
|
||||
<div class="actions"><button class="btn primary" id="p29-iv2-calc">Вычислить $F_A$</button></div>
|
||||
<div id="p29-iv2-out" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.96rem;line-height:1.7;text-align:center;min-height:40px"></div>
|
||||
</div>`;
|
||||
|
||||
/* INTERACTIVE 3 — Куда направлена сила Ампера? */
|
||||
html += `<div class="wg" id="p29-iv3">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Куда направлена сила Ампера?</div></div>
|
||||
<div class="wg-help">Используй правило левой руки. 6 ситуаций.</div>
|
||||
<div class="score-display"><span>Задача <b id="p29-iv3-i">1</b> / 6</span><span>Очки: <b id="p29-iv3-s">0</b> / 6</span></div>
|
||||
<div id="p29-iv3-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.02rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
|
||||
<div id="p29-iv3-opts" style="display:grid;grid-template-columns:1fr 1fr;gap:8px"></div>
|
||||
<div class="feedback" id="p29-iv3-fb"></div>
|
||||
<div class="actions"><button class="btn" id="p29-iv3-restart">Начать заново</button></div>
|
||||
</div>`;
|
||||
|
||||
/* INTERACTIVE 4 — Тренажёр (числовые ответы) */
|
||||
html += `<div class="wg" id="p29-iv4">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр: сила Ампера</div></div>
|
||||
<div class="wg-help">5 числовых задач. Допуск ±5%. Введи число и нажми Enter.</div>
|
||||
<div class="score-display"><span>Задача <b id="p29-iv4-i">1</b> / 5</span><span>Очки: <b id="p29-iv4-s">0</b> / 5</span></div>
|
||||
<div id="p29-iv4-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.02rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
|
||||
<div id="p29-iv4-form" style="display:flex;gap:8px;justify-content:center;margin-bottom:8px;flex-wrap:wrap">
|
||||
<input type="number" id="p29-iv4-inp" step="any" style="padding:8px 10px;border:1px solid var(--border);border-radius:6px;width:140px;font-size:1rem">
|
||||
<button class="btn primary" id="p29-iv4-go">Проверить</button>
|
||||
</div>
|
||||
<div class="feedback" id="p29-iv4-fb"></div>
|
||||
<div class="actions"><button class="btn" id="p29-iv4-restart">Начать заново</button></div>
|
||||
</div>`;
|
||||
|
||||
html += secNav('p28', 'p30');
|
||||
html += readButton('p29');
|
||||
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
|
||||
/* IV1 — Визуализатор правила левой руки */
|
||||
(function(){
|
||||
const svg = document.getElementById('p29-iv1-svg');
|
||||
const out = document.getElementById('p29-iv1-out');
|
||||
const bUp = document.getElementById('p29-iv1-up');
|
||||
const bDn = document.getElementById('p29-iv1-dn');
|
||||
const bRt = document.getElementById('p29-iv1-rt');
|
||||
const bLt = document.getElementById('p29-iv1-lt');
|
||||
const IS = document.getElementById('p29-iv1-I');
|
||||
const BS = document.getElementById('p29-iv1-B');
|
||||
const IL = document.getElementById('p29-iv1-IL');
|
||||
const BL = document.getElementById('p29-iv1-BL');
|
||||
const seen = new Set();
|
||||
let _done = false;
|
||||
let dir = 'up';
|
||||
|
||||
function setDir(d){
|
||||
dir = d;
|
||||
[bUp,bDn,bRt,bLt].forEach(b => b.classList.remove('primary'));
|
||||
({up:bUp,dn:bDn,rt:bRt,lt:bLt}[d]).classList.add('primary');
|
||||
render();
|
||||
}
|
||||
|
||||
function render(){
|
||||
const I = +IS.value, B = +BS.value;
|
||||
IL.textContent = I.toFixed(1);
|
||||
BL.textContent = B.toFixed(2);
|
||||
const W = 480, H = 320;
|
||||
let g = '';
|
||||
g += '<rect x="0" y="0" width="'+W+'" height="'+H+'" fill="#fafafa"/>';
|
||||
g += '<text x="240" y="22" text-anchor="middle" font-family="Inter,sans-serif" font-size="13" font-weight="700" fill="#0f172a">$\\vec{B}$ направлено в экран (×). Правило левой руки</text>'.replace('$\\vec{B}$','B');
|
||||
// Сетка магнитного поля (×)
|
||||
g += PHYS.magneticFieldGrid(50, 50, 380, 220, 8, 5, 'in');
|
||||
|
||||
const cx = 240, cy = 160;
|
||||
// Проводник с током
|
||||
const L = 90; // длина рисунка
|
||||
let x1,y1,x2,y2; // конечные точки тока (стрелка от начала к концу)
|
||||
if(dir === 'up'){ x1=cx; y1=cy+L; x2=cx; y2=cy-L; }
|
||||
else if(dir === 'dn'){ x1=cx; y1=cy-L; x2=cx; y2=cy+L; }
|
||||
else if(dir === 'rt'){ x1=cx-L; y1=cy; x2=cx+L; y2=cy; }
|
||||
else { x1=cx+L; y1=cy; x2=cx-L; y2=cy; }
|
||||
// Сам провод (в нейтральном цвете)
|
||||
g += '<line x1="'+(x1)+'" y1="'+(y1)+'" x2="'+(x2)+'" y2="'+(y2)+'" stroke="#0f172a" stroke-width="5" stroke-linecap="round" opacity=".25"/>';
|
||||
// Стрелка тока
|
||||
g += PHYS.drawArrow(x1, y1, x2, y2, '#dc2626', 3.5, 16);
|
||||
// Метка I
|
||||
const Imx = x2 + (dir==='rt'?14:dir==='lt'?-14:0);
|
||||
const Imy = y2 + (dir==='up'?-12:dir==='dn'?16:0);
|
||||
g += '<text x="'+Imx+'" y="'+Imy+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="14" font-weight="800" fill="#dc2626">I</text>';
|
||||
|
||||
// Направление силы по правилу левой руки (B в экран):
|
||||
// F = I × B. B = -z (в экран). I вверх (+y) → F = y × (-z) = -(y×z) = -x → влево
|
||||
// I вниз (-y) → F вправо. I вправо (+x) → F = x×(-z) = -(x×z) = +y? В экранных координатах y растёт вниз; но физический y вверх. В физической системе F=qv×B; в экранных: вверх — это -y_экр. Будем выводить так:
|
||||
// Take I dir (ix,iy экранные) and B = into page (z-out screen is "к нам", into page = -z_screen).
|
||||
// Use formula: F_screen = I_screen × B_into_screen. Cross with -ẑ: (ix, iy, 0) × (0,0,-1) = (iy*(-1) - 0, 0 - ix*(-1), 0) = (-iy, ix, 0)
|
||||
// For 'up': I=(0,-1) → F=(-(-1), 0)=(1,0) → вправо. But правило левой руки: B в экран, I вверх → F влево.
|
||||
// The discrepancy is sign of B. "В экран" we treated as B = -ẑ_screen. Let's check by physics: B is into page → in standard right-handed coord (x right, y up, z out of page) B = -ẑ. I up = +ŷ. F = IL × B = ŷ × (-ẑ) = -(ŷ×ẑ) = -x̂ → влево. Yes that matches.
|
||||
// In SCREEN coordinates: x_screen=x, y_screen=-y. So I_up means y_screen=-1, y_phys=+1. Convert back: ix_screen=0,iy_screen=-1 → ix_phys=0, iy_phys=+1.
|
||||
// Compute F in phys: ix_phys × B(=-ẑ) per above formula F_phys=(-iy_phys, ix_phys). For ix_phys=0,iy_phys=+1: F_phys=(-1,0) → x_phys=-1 → влево. ✓
|
||||
// To get F_screen we negate y: F_screen=(F_x_phys, -F_y_phys)=(-1,0) → влево. ✓
|
||||
// Generalize: given i_screen=(ix,iy), iy_phys=-iy. F_phys=(-iy_phys, ix_phys)=(iy, ix?). Wait ix_phys=ix. F_phys=(-iy_phys, ix_phys)=(iy, ix). Then F_screen=(F_x_phys, -F_y_phys)=(iy, -ix).
|
||||
// Test: up i_screen=(0,-1)→F_screen=(-1, 0)=влево ✓. down (0,1)→(1,0) вправо ✓. right (1,0)→(0,-1)=вверх ✓. left(-1,0)→(0,1)=вниз ✓.
|
||||
const map = { up:{ix:0,iy:-1, label:'вверх'}, dn:{ix:0,iy:1, label:'вниз'}, rt:{ix:1,iy:0, label:'вправо'}, lt:{ix:-1,iy:0, label:'влево'} };
|
||||
const cur = map[dir];
|
||||
const fx = cur.iy, fy = -cur.ix;
|
||||
const fLabel = (fx===1)?'вправо':(fx===-1)?'влево':(fy===-1)?'вверх':'вниз';
|
||||
// Рисуем силу: начинается из центра провода
|
||||
const fLen = 70;
|
||||
const fEndX = cx + fx * fLen;
|
||||
const fEndY = cy + fy * fLen;
|
||||
g += PHYS.drawArrow(cx, cy, fEndX, fEndY, '#0891b2', 4, 18);
|
||||
g += '<text x="'+(fEndX + fx*16)+'" y="'+(fEndY + fy*16 + (fy===0?4:0))+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="15" font-weight="800" fill="#0891b2">F</text>';
|
||||
|
||||
// Подпись внизу
|
||||
const Fmod = B * I * 1.0; // L=1 м
|
||||
g += '<text x="240" y="305" text-anchor="middle" font-family="Inter,sans-serif" font-size="12" fill="#64748b">L = 1 м, $\\alpha = 90°$</text>'.replace('$\\alpha = 90°$','α=90°');
|
||||
|
||||
svg.innerHTML = g;
|
||||
out.innerHTML = '<b>Ток '+cur.label+'</b>, $\\vec{B}$ в экран → сила Ампера <b>направлена '+fLabel+'</b>.<br>$F_A = B \\cdot I \\cdot L = '+B.toFixed(2)+' \\cdot '+I.toFixed(2)+' \\cdot 1 = '+Fmod.toFixed(2)+'$ Н.';
|
||||
renderMath(out);
|
||||
|
||||
seen.add(dir);
|
||||
if(!_done && seen.size >= 4){ _done = true; addXp(10, 'p29-iv1'); bumpProgress('p29', 15); }
|
||||
}
|
||||
|
||||
[bUp,bDn,bRt,bLt].forEach(b => b.addEventListener('click', () => setDir(b.dataset.d)));
|
||||
IS.addEventListener('input', render);
|
||||
BS.addEventListener('input', render);
|
||||
setDir('up');
|
||||
})();
|
||||
|
||||
/* IV2 — Калькулятор */
|
||||
(function(){
|
||||
const out = document.getElementById('p29-iv2-out');
|
||||
const bGo = document.getElementById('p29-iv2-calc');
|
||||
const inB = document.getElementById('p29-iv2-B');
|
||||
const inI = document.getElementById('p29-iv2-I');
|
||||
const inL = document.getElementById('p29-iv2-L');
|
||||
const inA = document.getElementById('p29-iv2-A');
|
||||
let count = 0, _done = false;
|
||||
|
||||
function calc(){
|
||||
const B = +inB.value, I = +inI.value, L = +inL.value, A = +inA.value;
|
||||
if(!isFinite(B)||!isFinite(I)||!isFinite(L)||!isFinite(A)){
|
||||
out.innerHTML = '<b style="color:#dc2626">Введи все значения.</b>';
|
||||
return;
|
||||
}
|
||||
const rad = A * Math.PI / 180;
|
||||
const F = B * I * L * Math.sin(rad);
|
||||
out.innerHTML = '$F_A = B \\cdot I \\cdot L \\cdot \\sin\\alpha = '+B+' \\cdot '+I+' \\cdot '+L+' \\cdot \\sin '+A+'° = \\mathbf{'+F.toFixed(4)+'}$ <b>Н</b>';
|
||||
renderMath(out);
|
||||
count++;
|
||||
if(!_done && count >= 3){ _done = true; addXp(10, 'p29-iv2'); bumpProgress('p29', 15); }
|
||||
}
|
||||
bGo.addEventListener('click', calc);
|
||||
[inB,inI,inL,inA].forEach(x => x.addEventListener('keydown', e => { if(e.key==='Enter') calc(); }));
|
||||
})();
|
||||
|
||||
/* IV3 — Куда направлена F_A? */
|
||||
(function(){
|
||||
const OPTS = ['Вправо','Влево','Вверх','Вниз'];
|
||||
const Q = [
|
||||
{ q:'$\\vec{B}$ в экран (×), ток вверх. Куда направлена $\\vec{F_A}$?', ans:1, why:'По правилу левой руки: B входит в ладонь, 4 пальца — вверх (ток), большой — влево.' },
|
||||
{ q:'$\\vec{B}$ из экрана (•), ток вверх. Куда направлена $\\vec{F_A}$?', ans:0, why:'B теперь из ладони, четыре пальца — вверх; большой палец — вправо.' },
|
||||
{ q:'$\\vec{B}$ в экран (×), ток вправо. Куда направлена $\\vec{F_A}$?', ans:2, why:'B входит в ладонь, пальцы — вправо; большой палец — вверх.' },
|
||||
{ q:'$\\vec{B}$ в экран (×), ток влево. Куда направлена $\\vec{F_A}$?', ans:3, why:'B входит в ладонь, пальцы — влево; большой палец — вниз.' },
|
||||
{ q:'$\\vec{B}$ из экрана (•), ток вниз. Куда направлена $\\vec{F_A}$?', ans:1, why:'B из ладони, пальцы — вниз; большой палец — влево.' },
|
||||
{ q:'$\\vec{B}$ из экрана (•), ток вправо. Куда направлена $\\vec{F_A}$?', ans:3, why:'B из ладони, пальцы — вправо; большой палец — вниз.' }
|
||||
];
|
||||
let i = 0, score = 0;
|
||||
const qEl = document.getElementById('p29-iv3-q');
|
||||
const oEl = document.getElementById('p29-iv3-opts');
|
||||
const fb = document.getElementById('p29-iv3-fb');
|
||||
const iEl = document.getElementById('p29-iv3-i');
|
||||
const sEl = document.getElementById('p29-iv3-s');
|
||||
|
||||
function show(){
|
||||
if(i >= Q.length){
|
||||
qEl.innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
|
||||
oEl.innerHTML = '';
|
||||
if(score === Q.length){ addXp(15, 'p29-iv3'); bumpProgress('p29', 25); }
|
||||
else if(score >= 4){ addXp(8, 'p29-iv3'); bumpProgress('p29', 15); }
|
||||
return;
|
||||
}
|
||||
iEl.textContent = (i+1);
|
||||
sEl.textContent = score;
|
||||
qEl.innerHTML = Q[i].q;
|
||||
oEl.innerHTML = OPTS.map((t, k) => '<button class="btn primary" data-v="' + k + '">' + t + '</button>').join('');
|
||||
fb.style.display = 'none';
|
||||
renderMath(qEl);
|
||||
oEl.querySelectorAll('button').forEach(b => {
|
||||
b.addEventListener('click', () => {
|
||||
const v = +b.dataset.v;
|
||||
if(v === Q[i].ans){ score++; feedback(fb, true, '✓ Верно! ' + Q[i].why + ' Дальше ▶'); }
|
||||
else feedback(fb, false, '✗ Верно: ' + OPTS[Q[i].ans] + '. ' + Q[i].why + ' Дальше ▶');
|
||||
sEl.textContent = score;
|
||||
oEl.querySelectorAll('button').forEach(x => x.disabled = true);
|
||||
i++;
|
||||
setTimeout(show, 1800);
|
||||
});
|
||||
});
|
||||
}
|
||||
document.getElementById('p29-iv3-restart').addEventListener('click', () => { i = 0; score = 0; show(); });
|
||||
show();
|
||||
})();
|
||||
|
||||
/* IV4 — Тренажёр числовой */
|
||||
(function(){
|
||||
const Q = [
|
||||
{ q:'$B = 0{,}5$ Тл, $I = 2$ А, $L = 0{,}1$ м, $\\alpha = 90°$. Найди $F_A$ (Н).', ans:0.1, tol:0.005, why:'$F_A = 0{,}5 \\cdot 2 \\cdot 0{,}1 \\cdot 1 = 0{,}1$ Н.' },
|
||||
{ q:'Те же данные, но $\\alpha = 30°$. Найди $F_A$ (Н).', ans:0.05, tol:0.005, why:'$F_A = 0{,}1 \\cdot \\sin 30° = 0{,}1 \\cdot 0{,}5 = 0{,}05$ Н.' },
|
||||
{ q:'При каком угле $\\alpha$ (в °, $0\\le\\alpha\\le 90$) сила Ампера равна нулю?', ans:0, tol:1, why:'$F_A = 0$ при $\\alpha = 0°$ (или $180°$): ток параллелен $\\vec{B}$.' },
|
||||
{ q:'$F_A = 0{,}4$ Н, $I = 2$ А, $L = 0{,}2$ м, $\\alpha = 90°$. Найди $B$ (Тл).', ans:1.0, tol:0.05, why:'$B = F/(IL) = 0{,}4/(2\\cdot 0{,}2) = 1$ Тл.' },
|
||||
{ q:'Проводник с током «вверх» в поле $\\vec{B}$, направленном в экран. Куда отклонится? Введи: 1 — вправо, 2 — влево, 3 — в экран, 4 — из экрана.', ans:2, tol:0, why:'По правилу левой руки сила направлена влево (ответ 2).' }
|
||||
];
|
||||
let i = 0, score = 0;
|
||||
const qEl = document.getElementById('p29-iv4-q');
|
||||
const fb = document.getElementById('p29-iv4-fb');
|
||||
const iEl = document.getElementById('p29-iv4-i');
|
||||
const sEl = document.getElementById('p29-iv4-s');
|
||||
const inp = document.getElementById('p29-iv4-inp');
|
||||
const bGo = document.getElementById('p29-iv4-go');
|
||||
|
||||
function show(){
|
||||
if(i >= Q.length){
|
||||
qEl.innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
|
||||
inp.disabled = true; bGo.disabled = true;
|
||||
if(score === Q.length){ addXp(15, 'p29-iv4'); bumpProgress('p29', 25); }
|
||||
else if(score >= 3){ addXp(8, 'p29-iv4'); bumpProgress('p29', 15); }
|
||||
return;
|
||||
}
|
||||
iEl.textContent = (i+1);
|
||||
sEl.textContent = score;
|
||||
qEl.innerHTML = Q[i].q;
|
||||
fb.style.display = 'none';
|
||||
inp.value = ''; inp.disabled = false; bGo.disabled = false; inp.focus();
|
||||
renderMath(qEl);
|
||||
}
|
||||
function check(){
|
||||
if(inp.disabled) return;
|
||||
const v = parseFloat(inp.value.replace(',','.'));
|
||||
if(!isFinite(v)){ feedback(fb, false, 'Введи число.'); return; }
|
||||
const ok = Math.abs(v - Q[i].ans) <= Math.max(Q[i].tol, Math.abs(Q[i].ans)*0.05);
|
||||
if(ok){ score++; feedback(fb, true, '✓ Верно! ' + Q[i].why + ' Дальше ▶'); }
|
||||
else feedback(fb, false, '✗ Верно: ' + Q[i].ans + '. ' + Q[i].why + ' Дальше ▶');
|
||||
sEl.textContent = score;
|
||||
inp.disabled = true; bGo.disabled = true;
|
||||
i++;
|
||||
setTimeout(show, 1900);
|
||||
}
|
||||
bGo.addEventListener('click', check);
|
||||
inp.addEventListener('keydown', e => { if(e.key==='Enter') check(); });
|
||||
document.getElementById('p29-iv4-restart').addEventListener('click', () => { i = 0; score = 0; inp.disabled=false; bGo.disabled=false; show(); });
|
||||
show();
|
||||
})();
|
||||
|
||||
wireReadBtn('p29');
|
||||
}
|
||||
|
||||
function build_p30(){
|
||||
const box = document.getElementById('p30-body');
|
||||
let html = '';
|
||||
|
||||
/* THEORY 1 — Сила Лоренца */
|
||||
html += makeCard('theory', "Сила Лоренца", "§30", `
|
||||
<p><b>Сила Лоренца</b> — этот параграф в разработке (Phase 1+).</p>
|
||||
<p>Здесь появятся: теория, формулы, разобранные примеры и 3–4 интерактива в стиле «алгебры 11» — таблицы, симуляции, ползунки, drag-and-drop и автопроверяемые тренажёры.</p>
|
||||
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.92rem">
|
||||
<b>Phase 0:</b> создан скелет учебника. <b>Phase 5+:</b> наполнение этого § содержанием по учебнику «Физика 10» (Беларусь, 2019).
|
||||
</p>
|
||||
<p><b>Сила Лоренца</b> — сила, действующая на электрический заряд $q$, движущийся со скоростью $\\vec{v}$ в магнитном поле $\\vec{B}$.</p>
|
||||
<p style="margin-top:8px"><b>Модуль</b>:</p>
|
||||
<p style="text-align:center;margin:8px 0">$$F_L = |q|\\, v\\, B\\, \\sin\\alpha$$</p>
|
||||
<p>где $\\alpha$ — угол между $\\vec{v}$ и $\\vec{B}$.</p>
|
||||
<p style="margin-top:10px"><b>Направление</b>:</p>
|
||||
<ul style="margin:6px 0 6px 22px">
|
||||
<li>Для <b>положительного</b> заряда — по <b>правилу левой руки</b> (ладонь — $\\vec{B}$ входит, 4 пальца — направление $\\vec{v}$, большой палец — $\\vec{F_L}$).</li>
|
||||
<li>Для <b>отрицательного</b> заряда — <b>противоположно</b>.</li>
|
||||
</ul>
|
||||
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px"><b>Важнейшее свойство.</b> $\\vec{F_L} \\perp \\vec{v}$ всегда, значит <b>работа силы Лоренца равна нулю</b>. Магнитное поле <b>не меняет</b> модуль скорости (и кинетическую энергию) — только <b>направление</b> движения.</p>
|
||||
`);
|
||||
|
||||
/* THEORY 2 — Движение по окружности */
|
||||
html += makeCard('rule', "Движение заряда по окружности", "§30", `
|
||||
<p>Если заряд $q$ влетает в однородное магнитное поле <b>перпендикулярно</b> $\\vec{B}$ ($\\alpha = 90°$), он движется по <b>окружности</b>.</p>
|
||||
<p style="margin-top:8px">Сила Лоренца играет роль <b>центростремительной</b>:</p>
|
||||
<p style="text-align:center;margin:8px 0">$$|q|\\,v\\,B = \\dfrac{m v^2}{R}$$</p>
|
||||
<p>Отсюда <b>радиус окружности</b>:</p>
|
||||
<p style="text-align:center;margin:8px 0">$$R = \\dfrac{m v}{|q|\\,B}$$</p>
|
||||
<p style="margin-top:10px"><b>Период обращения</b> (циклотронный период):</p>
|
||||
<p style="text-align:center;margin:8px 0">$$T = \\dfrac{2\\pi R}{v} = \\dfrac{2\\pi m}{|q|\\,B}$$</p>
|
||||
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px"><b>Удивительный факт.</b> Период $T$ <b>не зависит</b> от скорости $v$! Это используется в <b>циклотронах</b>: частицы ускоряются, но за каждый оборот всё равно проходят за одно и то же время.</p>
|
||||
`);
|
||||
|
||||
/* THEORY 3 — Спираль и применение */
|
||||
html += makeCard('example', "Спираль и применение", "§30", `
|
||||
<p>Если $\\vec{v}$ направлена под произвольным углом к $\\vec{B}$ (не $0°$ и не $90°$), движение — по <b>винтовой линии</b> (спирали):</p>
|
||||
<ul style="margin:6px 0 6px 22px">
|
||||
<li>Компонента $v_{\\parallel}$ (вдоль $\\vec{B}$) даёт <b>прямолинейное</b> движение.</li>
|
||||
<li>Компонента $v_{\\perp}$ (поперёк $\\vec{B}$) — <b>круговое</b>.</li>
|
||||
<li>Сумма — <b>спираль</b>.</li>
|
||||
</ul>
|
||||
<p style="margin-top:10px"><b>Применение силы Лоренца:</b></p>
|
||||
<ul style="margin:6px 0 6px 22px">
|
||||
<li><b>Циклотрон, синхротрон</b> — ускорители заряженных частиц (Большой адронный коллайдер).</li>
|
||||
<li><b>Масс-спектрометр</b>: ионы одинаковой энергии, но разной массы движутся по окружностям разного радиуса $R \\propto m$ — это позволяет их разделить и измерить массы.</li>
|
||||
<li><b>МРТ</b> (магнитно-резонансная томография) использует магнитное поле для управления спинами протонов в тканях.</li>
|
||||
<li><b>Полярное сияние</b>: частицы солнечного ветра захватываются геомагнитным полем и движутся по спиралям вдоль линий поля Земли, возбуждая свечение атмосферы у полюсов.</li>
|
||||
<li><b>Кинескоп</b> (старые телевизоры): электронный луч отклоняется магнитным полем — строится изображение.</li>
|
||||
</ul>
|
||||
<p style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px"><b>Связь с §29.</b> Сила Ампера — это сумма сил Лоренца, действующих на все заряды-носители тока внутри проводника.</p>
|
||||
`);
|
||||
|
||||
/* INTERACTIVE 1 — 3D-движение заряда */
|
||||
html += `<div class="wg" id="p30-iv1">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Заряд в магнитном поле: окружность или прямая?</div></div>
|
||||
<div class="wg-help">$\\vec{B}$ направлено в экран (×). Выбери знак заряда, скорость и угол вхождения $\\alpha$. Смотри траекторию.</div>
|
||||
<div style="display:flex;gap:8px;justify-content:center;margin-bottom:10px;flex-wrap:wrap">
|
||||
<button class="btn primary" id="p30-iv1-pos">Заряд $q > 0$</button>
|
||||
<button class="btn" id="p30-iv1-neg">Заряд $q < 0$</button>
|
||||
</div>
|
||||
<div class="sliders">
|
||||
<label>$v$: <b id="p30-iv1-vL">5.0</b> усл. <input type="range" id="p30-iv1-v" min="1" max="10" value="5" step="0.1"></label>
|
||||
<label>$\\alpha$ (°): <b id="p30-iv1-aL">90</b> <input type="range" id="p30-iv1-a" min="0" max="90" value="90" step="5"></label>
|
||||
</div>
|
||||
<div style="display:flex;gap:6px;justify-content:center;margin-bottom:8px;flex-wrap:wrap">
|
||||
<button class="btn" id="p30-iv1-pause">Пауза</button>
|
||||
<button class="btn" id="p30-iv1-reset">Сброс</button>
|
||||
</div>
|
||||
<div style="background:var(--card);border:1px solid var(--border);border-radius:9px;padding:8px">
|
||||
<svg id="p30-iv1-svg" viewBox="0 0 480 320" width="100%" style="height:auto"></svg>
|
||||
</div>
|
||||
<div id="p30-iv1-out" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.94rem;line-height:1.7;text-align:center"></div>
|
||||
</div>`;
|
||||
|
||||
/* INTERACTIVE 2 — Калькулятор */
|
||||
html += `<div class="wg" id="p30-iv2">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 2</span><div class="wg-title">Калькулятор силы Лоренца, $R$ и $T$</div></div>
|
||||
<div class="wg-help">Введи параметры. Заряд $q$ — в единицах $e = 1{,}6\\cdot 10^{-19}$ Кл.</div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:10px">
|
||||
<label style="display:flex;flex-direction:column;gap:4px;font-size:.92rem">$q$ (в $e$):<input type="number" id="p30-iv2-q" value="1" step="0.1" style="padding:7px;border:1px solid var(--border);border-radius:6px"></label>
|
||||
<label style="display:flex;flex-direction:column;gap:4px;font-size:.92rem">$v$ (м/с):<input type="number" id="p30-iv2-v" value="1e6" step="any" style="padding:7px;border:1px solid var(--border);border-radius:6px"></label>
|
||||
<label style="display:flex;flex-direction:column;gap:4px;font-size:.92rem">$B$ (Тл):<input type="number" id="p30-iv2-B" value="0.1" step="0.01" style="padding:7px;border:1px solid var(--border);border-radius:6px"></label>
|
||||
<label style="display:flex;flex-direction:column;gap:4px;font-size:.92rem">$\\alpha$ (°):<input type="number" id="p30-iv2-A" value="90" step="1" min="0" max="180" style="padding:7px;border:1px solid var(--border);border-radius:6px"></label>
|
||||
<label style="display:flex;flex-direction:column;gap:4px;font-size:.92rem">$m$ (кг):<input type="number" id="p30-iv2-m" value="9.1e-31" step="any" style="padding:7px;border:1px solid var(--border);border-radius:6px"></label>
|
||||
</div>
|
||||
<div class="actions"><button class="btn primary" id="p30-iv2-calc">Вычислить</button></div>
|
||||
<div id="p30-iv2-out" style="margin-top:10px;padding:10px 14px;background:var(--sec-acc-soft);border-radius:9px;font-size:.96rem;line-height:1.8;text-align:center;min-height:40px"></div>
|
||||
</div>`;
|
||||
|
||||
/* INTERACTIVE 3 — Влияет ли поле на скорость? */
|
||||
html += `<div class="wg" id="p30-iv3">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 3</span><div class="wg-title">Влияет ли поле на модуль скорости?</div></div>
|
||||
<div class="wg-help">6 ситуаций. Магнитное поле не меняет $|\\vec{v}|$, электрическое — меняет.</div>
|
||||
<div class="score-display"><span>Задача <b id="p30-iv3-i">1</b> / 6</span><span>Очки: <b id="p30-iv3-s">0</b> / 6</span></div>
|
||||
<div id="p30-iv3-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.02rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
|
||||
<div id="p30-iv3-opts" style="display:grid;grid-template-columns:1fr 1fr;gap:8px"></div>
|
||||
<div class="feedback" id="p30-iv3-fb"></div>
|
||||
<div class="actions"><button class="btn" id="p30-iv3-restart">Начать заново</button></div>
|
||||
</div>`;
|
||||
|
||||
/* INTERACTIVE 4 — Тренажёр числовой */
|
||||
html += `<div class="wg" id="p30-iv4">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 4</span><div class="wg-title">Тренажёр: сила Лоренца</div></div>
|
||||
<div class="wg-help">5 числовых задач. Допуск ±5%. Используй $e = 1{,}6\\cdot 10^{-19}$ Кл.</div>
|
||||
<div class="score-display"><span>Задача <b id="p30-iv4-i">1</b> / 5</span><span>Очки: <b id="p30-iv4-s">0</b> / 5</span></div>
|
||||
<div id="p30-iv4-q" style="padding:14px;background:var(--sec-acc-soft);border-radius:10px;font-size:1.02rem;margin-bottom:10px;text-align:center;min-height:54px"></div>
|
||||
<div id="p30-iv4-form" style="display:flex;gap:8px;justify-content:center;margin-bottom:8px;flex-wrap:wrap">
|
||||
<input type="number" id="p30-iv4-inp" step="any" style="padding:8px 10px;border:1px solid var(--border);border-radius:6px;width:140px;font-size:1rem">
|
||||
<button class="btn primary" id="p30-iv4-go">Проверить</button>
|
||||
</div>
|
||||
<div class="feedback" id="p30-iv4-fb"></div>
|
||||
<div class="actions"><button class="btn" id="p30-iv4-restart">Начать заново</button></div>
|
||||
</div>`;
|
||||
|
||||
html += secNav('p29', 'p31');
|
||||
html += readButton('p30');
|
||||
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
|
||||
/* IV1 — Симуляция движения заряда */
|
||||
(function(){
|
||||
const svg = document.getElementById('p30-iv1-svg');
|
||||
const out = document.getElementById('p30-iv1-out');
|
||||
const bPos = document.getElementById('p30-iv1-pos');
|
||||
const bNeg = document.getElementById('p30-iv1-neg');
|
||||
const bPause = document.getElementById('p30-iv1-pause');
|
||||
const bReset = document.getElementById('p30-iv1-reset');
|
||||
const vS = document.getElementById('p30-iv1-v');
|
||||
const aS = document.getElementById('p30-iv1-a');
|
||||
const vL = document.getElementById('p30-iv1-vL');
|
||||
const aL = document.getElementById('p30-iv1-aL');
|
||||
const seen = new Set();
|
||||
let _done = false;
|
||||
let sign = +1;
|
||||
let paused = false;
|
||||
let t0 = performance.now();
|
||||
let trail = [];
|
||||
|
||||
function setSign(s){ sign = s; bPos.classList.toggle('primary', s>0); bNeg.classList.toggle('primary', s<0); reset(); }
|
||||
function reset(){ t0 = performance.now(); trail = []; }
|
||||
|
||||
function draw(){
|
||||
const W = 480, H = 320;
|
||||
const v = +vS.value, aDeg = +aS.value;
|
||||
vL.textContent = v.toFixed(1);
|
||||
aL.textContent = aDeg.toFixed(0);
|
||||
const alpha = aDeg * Math.PI / 180;
|
||||
|
||||
const now = performance.now();
|
||||
if(!paused){
|
||||
// Эта функция всё равно вызывается через rAF, accumulator подразумевается через t0
|
||||
}
|
||||
const tSec = (now - t0) / 1000;
|
||||
|
||||
let g = '';
|
||||
g += '<rect x="0" y="0" width="'+W+'" height="'+H+'" fill="#fafafa"/>';
|
||||
g += '<text x="240" y="22" text-anchor="middle" font-family="Inter,sans-serif" font-size="13" font-weight="700" fill="#0f172a">B в экран (×). q = '+(sign>0?'+':'−')+', α='+aDeg+'°</text>';
|
||||
g += PHYS.magneticFieldGrid(50, 50, 380, 230, 8, 5, 'in');
|
||||
|
||||
// Параметры
|
||||
const cx = 240, cy = 165;
|
||||
const vPerp = Math.sin(alpha) * v;
|
||||
const vPar = Math.cos(alpha) * v;
|
||||
// Радиус и угловая скорость (упрощённо, безразмерно)
|
||||
const Rsim = Math.max(8, vPerp * 12); // px
|
||||
const omega = (vPerp > 0.001) ? (sign * 0.9) : 0; // рад/с (направление: + → против часовой? Для q>0, B в экран — по часовой)
|
||||
// Для q>0, B в экран: F=qv×B. Скорость вправо (+x), B=-z (в экран). F=q(x×-z)=q(+y)=вверх. Значит, частица идущая вправо испытывает силу вверх — она поворачивает вверх. Это против часовой стрелки в экранных координатах (y растёт вниз). Проверим: для CCW (против часовой в экране) с угла θ=0 → x=R, y=0 (вправо); скорость в этот момент должна быть вверх (-y_экр). dθ/dt > 0 → x=Rcos(θ),y=-Rsin(θ)? Нет, упрощу — выберу знак.
|
||||
// В экранных координатах: для q>0 (B в экран) движение по часовой стрелке. Возьмём знак omega = -sign (по часовой = в экране отрицательный угол).
|
||||
const dir_sign = -sign; // для anim
|
||||
const ang0 = Math.PI; // начинать слева
|
||||
const ang = ang0 + dir_sign * 1.2 * tSec * (vPerp/5);
|
||||
// Спираль: смещение по линии B → в нашем 2D представлении сместим центр окружности вдоль некоторого направления (вверх — представим как «вдоль B», условно)
|
||||
// Поскольку B в экран — vPar выходит из экрана; в 2D не виден. Покажем как точку, мигающую с прогрессом.
|
||||
const px = cx + Rsim * Math.cos(ang);
|
||||
const py = cy + Rsim * Math.sin(ang);
|
||||
|
||||
if(!paused){
|
||||
trail.push([px,py]);
|
||||
if(trail.length > 200) trail.shift();
|
||||
}
|
||||
|
||||
if(aDeg === 0){
|
||||
// Прямолинейное движение (v параллельно B → точка просто стоит/уходит "в экран")
|
||||
g += '<text x="240" y="160" text-anchor="middle" font-family="Inter,sans-serif" font-size="13" fill="#64748b">$\\vec{v} \\parallel \\vec{B}$ → сила не действует, движение прямолинейное.</text>'.replace('$\\vec{v} \\parallel \\vec{B}$','v ∥ B');
|
||||
g += PHYS.chargeMark(cx, cy, sign, 14, sign>0?'+':'−');
|
||||
} else if(aDeg === 90){
|
||||
// Окружность
|
||||
g += '<circle cx="'+cx+'" cy="'+cy+'" r="'+Rsim.toFixed(1)+'" fill="none" stroke="#7c3aed" stroke-width="1.4" stroke-dasharray="4 3" opacity=".55"/>';
|
||||
// Трейл
|
||||
if(trail.length >= 2){
|
||||
let path = 'M '+trail[0][0].toFixed(1)+' '+trail[0][1].toFixed(1);
|
||||
for(let k=1;k<trail.length;k++) path += ' L '+trail[k][0].toFixed(1)+' '+trail[k][1].toFixed(1);
|
||||
g += '<path d="'+path+'" stroke="#0891b2" stroke-width="2" fill="none" opacity=".85"/>';
|
||||
}
|
||||
// Текущая позиция — заряд
|
||||
g += PHYS.chargeMark(px, py, sign, 11, sign>0?'+':'−');
|
||||
// Вектор скорости (касательная)
|
||||
const vAng = ang + dir_sign * Math.PI/2;
|
||||
const vEx = px + 28 * Math.cos(vAng);
|
||||
const vEy = py + 28 * Math.sin(vAng);
|
||||
g += PHYS.drawArrow(px, py, vEx, vEy, '#dc2626', 2, 10);
|
||||
g += '<text x="'+(vEx+8)+'" y="'+(vEy-4)+'" font-family="JetBrains Mono,monospace" font-size="12" font-weight="700" fill="#dc2626">v</text>';
|
||||
// Вектор силы (центростремительная — к центру)
|
||||
const fEx = px + 28 * Math.cos(ang + Math.PI);
|
||||
const fEy = py + 28 * Math.sin(ang + Math.PI);
|
||||
g += PHYS.drawArrow(px, py, fEx, fEy, '#0891b2', 2, 10);
|
||||
g += '<text x="'+(fEx-8)+'" y="'+(fEy+12)+'" font-family="JetBrains Mono,monospace" font-size="12" font-weight="700" fill="#0891b2">F</text>';
|
||||
} else {
|
||||
// Спираль — рисуем как смещённую окружность
|
||||
g += '<circle cx="'+cx+'" cy="'+cy+'" r="'+Rsim.toFixed(1)+'" fill="none" stroke="#7c3aed" stroke-width="1.2" stroke-dasharray="3 3" opacity=".4"/>';
|
||||
if(trail.length >= 2){
|
||||
let path = 'M '+trail[0][0].toFixed(1)+' '+trail[0][1].toFixed(1);
|
||||
for(let k=1;k<trail.length;k++) path += ' L '+trail[k][0].toFixed(1)+' '+trail[k][1].toFixed(1);
|
||||
g += '<path d="'+path+'" stroke="#0891b2" stroke-width="2" fill="none" opacity=".8"/>';
|
||||
}
|
||||
g += PHYS.chargeMark(px, py, sign, 11, sign>0?'+':'−');
|
||||
g += '<text x="240" y="305" text-anchor="middle" font-family="Inter,sans-serif" font-size="12" fill="#64748b">Спираль (винтовая линия): $v_{\\perp}$ → круг, $v_{\\parallel}$ → вдоль B</text>'.replace('$v_{\\perp}$','v⊥').replace('$v_{\\parallel}$','v∥');
|
||||
}
|
||||
|
||||
svg.innerHTML = g;
|
||||
|
||||
let txt = '';
|
||||
if(aDeg === 0){
|
||||
txt = '<b>$\\alpha = 0°$:</b> $\\vec{v} \\parallel \\vec{B}$, $F_L = 0$. Прямолинейное движение, поле не действует.';
|
||||
} else if(aDeg === 90){
|
||||
txt = '<b>$\\alpha = 90°$:</b> чистая окружность. $R = mv/(|q|B)$, $T = 2\\pi m/(|q|B)$ (не зависит от $v$).';
|
||||
} else {
|
||||
txt = '<b>$\\alpha = '+aDeg+'°$:</b> винтовая линия. $v_{\\parallel}$ вдоль $\\vec{B}$ + $v_{\\perp}$ по окружности.';
|
||||
}
|
||||
out.innerHTML = txt;
|
||||
renderMath(out);
|
||||
|
||||
seen.add(sign+':'+aDeg);
|
||||
if(!_done && seen.size >= 4){ _done = true; addXp(10, 'p30-iv1'); bumpProgress('p30', 15); }
|
||||
}
|
||||
|
||||
function loop(){
|
||||
if(!paused) draw();
|
||||
requestAnimationFrame(loop);
|
||||
}
|
||||
|
||||
bPos.addEventListener('click', () => setSign(+1));
|
||||
bNeg.addEventListener('click', () => setSign(-1));
|
||||
bPause.addEventListener('click', () => { paused = !paused; bPause.textContent = paused ? 'Продолжить' : 'Пауза'; });
|
||||
bReset.addEventListener('click', reset);
|
||||
vS.addEventListener('input', () => { reset(); draw(); });
|
||||
aS.addEventListener('input', () => { reset(); draw(); });
|
||||
setSign(+1);
|
||||
draw();
|
||||
requestAnimationFrame(loop);
|
||||
})();
|
||||
|
||||
/* IV2 — Калькулятор */
|
||||
(function(){
|
||||
const out = document.getElementById('p30-iv2-out');
|
||||
const bGo = document.getElementById('p30-iv2-calc');
|
||||
const inQ = document.getElementById('p30-iv2-q');
|
||||
const inV = document.getElementById('p30-iv2-v');
|
||||
const inB = document.getElementById('p30-iv2-B');
|
||||
const inA = document.getElementById('p30-iv2-A');
|
||||
const inM = document.getElementById('p30-iv2-m');
|
||||
let count = 0, _done = false;
|
||||
|
||||
function calc(){
|
||||
const qe = +inQ.value, v = +inV.value, B = +inB.value, aDeg = +inA.value, m = +inM.value;
|
||||
if(![qe,v,B,aDeg,m].every(isFinite)){ out.innerHTML = '<b style="color:#dc2626">Введи все значения.</b>'; return; }
|
||||
const e = PHYS.CONST.e;
|
||||
const q = qe * e;
|
||||
const rad = aDeg * Math.PI / 180;
|
||||
const F = Math.abs(q) * v * B * Math.sin(rad);
|
||||
let html = '$F_L = |q|\\,v\\,B\\,\\sin\\alpha = '+F.toExponential(3)+'$ <b>Н</b>';
|
||||
if(Math.abs(aDeg - 90) < 1e-6 && Math.abs(q) > 0 && B > 0){
|
||||
const R = m * v / (Math.abs(q) * B);
|
||||
const T = 2 * Math.PI * m / (Math.abs(q) * B);
|
||||
html += '<br>При $\\alpha = 90°$: $R = mv/(|q|B) = '+R.toExponential(3)+'$ м, $T = 2\\pi m/(|q|B) = '+T.toExponential(3)+'$ с.';
|
||||
}
|
||||
out.innerHTML = html;
|
||||
renderMath(out);
|
||||
count++;
|
||||
if(!_done && count >= 3){ _done = true; addXp(10, 'p30-iv2'); bumpProgress('p30', 15); }
|
||||
}
|
||||
bGo.addEventListener('click', calc);
|
||||
[inQ,inV,inB,inA,inM].forEach(x => x.addEventListener('keydown', e => { if(e.key==='Enter') calc(); }));
|
||||
})();
|
||||
|
||||
/* IV3 — Влияет ли поле на скорость? */
|
||||
(function(){
|
||||
const OPTS = ['Меняет модуль скорости','Не меняет (только направление, или сила = 0)'];
|
||||
const Q = [
|
||||
{ q:'Электрон, влетевший в однородное магнитное поле перпендикулярно $\\vec{B}$.', ans:1, why:'Сила Лоренца $\\perp \\vec{v}$, работа = 0, $|\\vec{v}|$ постоянен.' },
|
||||
{ q:'Электрон в однородном электрическом поле $\\vec{E}$.', ans:0, why:'Электрическое поле совершает работу, $|\\vec{v}|$ меняется.' },
|
||||
{ q:'Протон движется параллельно $\\vec{B}$.', ans:1, why:'$\\alpha = 0$ → $F_L = 0$. Прямолинейное равномерное движение.' },
|
||||
{ q:'Нейтрон (заряд = 0) в магнитном поле.', ans:1, why:'$q = 0$ → $F_L = 0$. Поле никак не действует.' },
|
||||
{ q:'Положительный заряд в однородном поле $\\vec{B}$, $\\vec{v} \\perp \\vec{B}$.', ans:1, why:'Движение по окружности, $|\\vec{v}|$ постоянен — только направление меняется.' },
|
||||
{ q:'Электрон в комбинированном поле $\\vec{E} + \\vec{B}$.', ans:0, why:'Из-за $\\vec{E}$ работа $\\ne 0$, поэтому $|\\vec{v}|$ меняется.' }
|
||||
];
|
||||
let i = 0, score = 0;
|
||||
const qEl = document.getElementById('p30-iv3-q');
|
||||
const oEl = document.getElementById('p30-iv3-opts');
|
||||
const fb = document.getElementById('p30-iv3-fb');
|
||||
const iEl = document.getElementById('p30-iv3-i');
|
||||
const sEl = document.getElementById('p30-iv3-s');
|
||||
|
||||
function show(){
|
||||
if(i >= Q.length){
|
||||
qEl.innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
|
||||
oEl.innerHTML = '';
|
||||
if(score === Q.length){ addXp(15, 'p30-iv3'); bumpProgress('p30', 25); }
|
||||
else if(score >= 4){ addXp(8, 'p30-iv3'); bumpProgress('p30', 15); }
|
||||
return;
|
||||
}
|
||||
iEl.textContent = (i+1);
|
||||
sEl.textContent = score;
|
||||
qEl.innerHTML = Q[i].q;
|
||||
oEl.innerHTML = OPTS.map((t, k) => '<button class="btn primary" data-v="' + k + '">' + t + '</button>').join('');
|
||||
fb.style.display = 'none';
|
||||
renderMath(qEl);
|
||||
oEl.querySelectorAll('button').forEach(b => {
|
||||
b.addEventListener('click', () => {
|
||||
const v = +b.dataset.v;
|
||||
if(v === Q[i].ans){ score++; feedback(fb, true, '✓ Верно! ' + Q[i].why + ' Дальше ▶'); }
|
||||
else feedback(fb, false, '✗ Верно: ' + OPTS[Q[i].ans] + '. ' + Q[i].why + ' Дальше ▶');
|
||||
sEl.textContent = score;
|
||||
oEl.querySelectorAll('button').forEach(x => x.disabled = true);
|
||||
i++;
|
||||
setTimeout(show, 1800);
|
||||
});
|
||||
});
|
||||
}
|
||||
document.getElementById('p30-iv3-restart').addEventListener('click', () => { i = 0; score = 0; show(); });
|
||||
show();
|
||||
})();
|
||||
|
||||
/* IV4 — Тренажёр числовой */
|
||||
(function(){
|
||||
const Q = [
|
||||
{ q:'$q = e$, $v = 10^6$ м/с, $B = 0{,}1$ Тл, $\\alpha = 90°$. Найди $F_L$. Введи мантиссу при $10^{-14}$ Н.', ans:1.6, tol:0.1, why:'$F_L = 1{,}6\\cdot 10^{-19}\\cdot 10^6\\cdot 0{,}1 = 1{,}6\\cdot 10^{-14}$ Н.' },
|
||||
{ q:'Электрон ($m = 9{,}1\\cdot 10^{-31}$ кг) в $B = 10^{-3}$ Тл, $v = 10^7$ м/с, $\\alpha = 90°$. Найди $R$ (см).', ans:5.7, tol:0.5, why:'$R = mv/(|q|B) = 9{,}1\\cdot 10^{-31}\\cdot 10^7 / (1{,}6\\cdot 10^{-19}\\cdot 10^{-3}) \\approx 5{,}7\\cdot 10^{-2}$ м = 5,7 см.' },
|
||||
{ q:'При $\\alpha = 0°$ сила Лоренца равна (в Н)?', ans:0, tol:1e-30, why:'$F_L = qvB\\sin 0° = 0$. Сила не действует.' },
|
||||
{ q:'Работа силы Лоренца за период обращения частицы по окружности (в Дж)?', ans:0, tol:1e-30, why:'$\\vec{F_L} \\perp \\vec{v}$, поэтому $A = 0$ всегда.' },
|
||||
{ q:'Если скорость заряда удвоить (при $\\alpha=90°$), во сколько раз изменится радиус $R$?', ans:2, tol:0.1, why:'$R = mv/(|q|B) \\propto v$ → удваивается. Период $T$ не меняется.' }
|
||||
];
|
||||
let i = 0, score = 0;
|
||||
const qEl = document.getElementById('p30-iv4-q');
|
||||
const fb = document.getElementById('p30-iv4-fb');
|
||||
const iEl = document.getElementById('p30-iv4-i');
|
||||
const sEl = document.getElementById('p30-iv4-s');
|
||||
const inp = document.getElementById('p30-iv4-inp');
|
||||
const bGo = document.getElementById('p30-iv4-go');
|
||||
|
||||
function show(){
|
||||
if(i >= Q.length){
|
||||
qEl.innerHTML = '<b>Готово!</b> Результат: ' + score + ' / ' + Q.length;
|
||||
inp.disabled = true; bGo.disabled = true;
|
||||
if(score === Q.length){ addXp(15, 'p30-iv4'); bumpProgress('p30', 25); }
|
||||
else if(score >= 3){ addXp(8, 'p30-iv4'); bumpProgress('p30', 15); }
|
||||
return;
|
||||
}
|
||||
iEl.textContent = (i+1);
|
||||
sEl.textContent = score;
|
||||
qEl.innerHTML = Q[i].q;
|
||||
fb.style.display = 'none';
|
||||
inp.value = ''; inp.disabled = false; bGo.disabled = false; inp.focus();
|
||||
renderMath(qEl);
|
||||
}
|
||||
function check(){
|
||||
if(inp.disabled) return;
|
||||
const v = parseFloat(inp.value.replace(',','.'));
|
||||
if(!isFinite(v)){ feedback(fb, false, 'Введи число.'); return; }
|
||||
const tol = Math.max(Q[i].tol, Math.abs(Q[i].ans)*0.05);
|
||||
const ok = Math.abs(v - Q[i].ans) <= tol;
|
||||
if(ok){ score++; feedback(fb, true, '✓ Верно! ' + Q[i].why + ' Дальше ▶'); }
|
||||
else feedback(fb, false, '✗ Верно: ' + Q[i].ans + '. ' + Q[i].why + ' Дальше ▶');
|
||||
sEl.textContent = score;
|
||||
inp.disabled = true; bGo.disabled = true;
|
||||
i++;
|
||||
setTimeout(show, 1900);
|
||||
}
|
||||
bGo.addEventListener('click', check);
|
||||
inp.addEventListener('keydown', e => { if(e.key==='Enter') check(); });
|
||||
document.getElementById('p30-iv4-restart').addEventListener('click', () => { i = 0; score = 0; inp.disabled=false; bGo.disabled=false; show(); });
|
||||
show();
|
||||
})();
|
||||
|
||||
wireReadBtn('p30');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user