From 33f968bff9945f6b422b41b3f87e2c7430ef9516 Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Sat, 30 May 2026 19:51:27 +0300 Subject: [PATCH] =?UTF-8?q?feat(chemistry7):=20=D0=B2=D0=B8=D0=B7=D1=83?= =?UTF-8?q?=D0=B0=D0=BB=20V3=20(=D0=93=D0=BB=D0=B0=D0=B2=D0=B0=203)=20?= =?UTF-8?q?=E2=80=94=20=D0=BF=D1=83=D0=B7=D1=8B=D1=80=D1=8C=D0=BA=D0=B8,?= =?UTF-8?q?=20=D0=BC=D0=BE=D1=80=D1=84=D0=B8=D0=BD=D0=B3=20=D1=86=D0=B2?= =?UTF-8?q?=D0=B5=D1=82=D0=B0,=20=D0=B8=D0=BD=D0=B4=D0=B8=D0=BA=D0=B0?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Подключён chem7_anim.js в Главу 3. - §21 ряд активности (звёздный): клик металла левее H₂ → анимация пузырьков H₂ (bubbleField); правее (Cu, Ag) — «реакция не идёт»; - §19 восстановление CuO: colorBlock плавно чёрный→красный (медь); горение — пламя водорода; - §20/ЛО3 индикаторы: блок плавно меняет цвет на цвет индикатора в кислоте. Тесты chem7: 16/16; полный прогон 162/165 (3 — baseline Auth). Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/tests/chemistry7-page.test.js | 5 ++++ frontend/js/chem7_ch3_widgets.js | 35 ++++++++++++++++++------- frontend/textbooks/chemistry_7_ch3.html | 1 + 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/backend/tests/chemistry7-page.test.js b/backend/tests/chemistry7-page.test.js index 475df7e..2789b82 100644 --- a/backend/tests/chemistry7-page.test.js +++ b/backend/tests/chemistry7-page.test.js @@ -194,8 +194,10 @@ test('ch3 Волна 1: §18 + §19 + §20 + ЛО3 монтируются', asyn assert.ok(doc.querySelector('#p18-card svg'), 'паспорт водорода §18'); doc.defaultView.goTo('p19'); await wait(100); assert.ok(doc.querySelector('#p19-rx #p19-pick'), 'реакции водорода §19'); + assert.ok(doc.querySelector('#p19-stage div'), 'анимация реакции §19'); doc.defaultView.goTo('p20'); await wait(100); assert.ok(doc.querySelector('#p20-ind #p20-ind-ind'), 'индикаторы §20'); + assert.ok(doc.querySelector('#p20-ind-drop div'), 'анимация индикатора §20'); assert.ok(doc.querySelector('#p20-acids table'), 'таблица кислот §20'); doc.defaultView.goTo('lo3'); await wait(100); assert.ok(doc.querySelector('#lo3-ind #lo3-ind-ind'), 'индикаторы ЛО3'); @@ -206,6 +208,9 @@ test('ch3 Волна 2: §21 + ЛО4 + §22 + ПР3 + финал главы мо const { doc, errors } = await loadDom('chemistry_7_ch3.html'); doc.defaultView.goTo('p21'); await wait(100); assert.ok(doc.querySelector('#p21-act .act-cell'), 'ряд активности §21'); + // клик по Zn (левее H₂) → пузырьки H₂ + doc.querySelector('#p21-act .act-cell[data-i="5"]').dispatchEvent(new doc.defaultView.Event('click', { bubbles: true })); await wait(40); + assert.ok(doc.querySelector('#p21-tube div'), 'пузырьки H₂ при реакции металла с кислотой §21'); doc.defaultView.goTo('lo4'); await wait(100); assert.ok(doc.querySelector('#lo4-rx #lo4-go'), 'опыт металл+кислота ЛО4'); doc.defaultView.goTo('p22'); await wait(100); diff --git a/frontend/js/chem7_ch3_widgets.js b/frontend/js/chem7_ch3_widgets.js index 2369a47..a13bdfd 100644 --- a/frontend/js/chem7_ch3_widgets.js +++ b/frontend/js/chem7_ch3_widgets.js @@ -35,14 +35,21 @@ ]; function mount_p19() { var m = $('p19-rx'); if (!m || m._built) return; m._built = 1; - var idx = 0; + var idx = 0, anim = null; + function stopAnim(){ if(anim){anim.stop();anim=null;} } function render(){ + stopAnim(); var r = RX[idx]; - var swatch = idx===1 ? '
CuO (чёрный) → Cu (красный)
' : ''; m.innerHTML = '
' - + '
' + ceq(r.eq) + '
' + esc(r.note) + '
' + swatch + '
'; - $('p19-pick').addEventListener('change', function(e){ idx=+e.target.value; m._built=0; render(); }); + + '
' + + '
' + ceq(r.eq) + '
' + esc(r.note) + '
'; + var stage = $('p19-stage'); + if (stage && W.Chem7Anim) { + if (idx === 1) anim = W.Chem7Anim.colorBlock(stage, '#1f2937', '#b45309', 'CuO (чёрный) → Cu (красная медь)', 1800); + else anim = W.Chem7Anim.flameBox(stage, { color: '#93c5fd' }); + } + $('p19-pick').addEventListener('change', function(e){ idx=+e.target.value; render(); }); } render(); } @@ -60,17 +67,20 @@ }; function indicatorWidget(mountId, withAcidPick) { var m = $(mountId); if (!m || m._built) return; m._built = 1; - var ind = 'Лакмус', acid = 0; + var ind = 'Лакмус', acid = 0, anim = null; function strip(color){ return '
'; } function render(){ + if (anim) { anim.stop(); anim = null; } var a = ACIDS[acid], col = INDIC[ind]; m.innerHTML = '
' + (withAcidPick ? '' : '') + '
' + + '
' + '
В нейтральной среде: ' + strip(col.neutral[0]) + ' '+col.neutral[1]+'
' + 'В кислоте' + (withAcidPick?(' ('+fml(a.f)+')'):'') + ': ' + strip(col.acid[0]) + ' '+col.acid[1]+'
'; - $(mountId+'-ind').addEventListener('change', function(e){ ind=e.target.value; m._built=0; render(); }); - if (withAcidPick) $(mountId+'-acid').addEventListener('change', function(e){ acid=+e.target.value; m._built=0; render(); }); + if (W.Chem7Anim) anim = W.Chem7Anim.colorBlock($(mountId+'-drop'), col.neutral[0], col.acid[0], ind + ' в кислоте → ' + col.acid[1], 900); + $(mountId+'-ind').addEventListener('change', function(e){ ind=e.target.value; render(); }); + if (withAcidPick) $(mountId+'-acid').addEventListener('change', function(e){ acid=+e.target.value; render(); }); } render(); } @@ -87,21 +97,26 @@ var ROW = ['K','Ca','Na','Mg','Al','Zn','Fe','Ni','Sn','Pb','H','Cu','Hg','Ag','Pt','Au']; function mount_p21() { var m = $('p21-act'); if (!m || m._built) return; m._built = 1; - var hIdx = ROW.indexOf('H'); + var hIdx = ROW.indexOf('H'), anim = null; + function stopAnim(){ if(anim){anim.stop();anim=null;} } m.innerHTML = '
' + ROW.map(function(el,i){ var isH=el==='H'; return ''; }).join('') + '
' - + '
Слева активность убывает вправо. Граница — водород H₂.
' + + '
Слева активность убывает вправо. Граница — водород H₂. Кликни металл — «опусти» его в кислоту.
' + + '
' + '
Кликни по металлу — узнаешь, вытесняет ли он водород из кислоты.
'; var out = $('p21-act-out'); m.querySelectorAll('.act-cell').forEach(function(b){ b.addEventListener('click', function(){ - var i=+b.dataset.i, el=ROW[i]; if(el==='H'){ out.className='out'; out.innerHTML='Водород H₂ — граница ряда активности.'; return; } + var i=+b.dataset.i, el=ROW[i], tube=$('p21-tube'); stopAnim(); + if(el==='H'){ out.className='out'; out.innerHTML='Водород H₂ — граница ряда активности.'; if(tube)tube.innerHTML=''; return; } out.className='out ok'; if(iВнимание: очень активный металл — с кислотами реагирует бурно (для получения водорода используют Zn, Fe).' : ''; out.innerHTML = ''+el+' стоит левее H₂ → вытесняет водород из соляной и серной кислот: образуются соль и $H_2\\uparrow$.'+extra; + if (tube && W.Chem7Anim) anim = W.Chem7Anim.bubbleField(tube, { color:'rgba(255,255,255,.85)', h:96 }); } else { out.innerHTML = ''+el+' стоит правее H₂ → водород из кислот не вытесняет (например, медь и серебро с этими кислотами не реагируют).'; + if (tube) tube.innerHTML = '
реакция не идёт — пузырьков нет
'; } if (W.chem8RenderMath) try { W.chem8RenderMath(out); } catch(e){} }); diff --git a/frontend/textbooks/chemistry_7_ch3.html b/frontend/textbooks/chemistry_7_ch3.html index 21f31e1..4adf69e 100644 --- a/frontend/textbooks/chemistry_7_ch3.html +++ b/frontend/textbooks/chemistry_7_ch3.html @@ -23,6 +23,7 @@ html.dark{--bg:#140a24;--border:#3b2a63;--pri-soft:rgba(124,58,237,.18);--sec-ac +