feat(chemistry7): визуал V1 — анимация §10 (признаки реакции) и §11 (осадок)
chem7_anim.js: CSS-хелперы (jsdom-safe, без canvas) — bubbleField (пузырьки газа), precipField (падающий осадок + слой), flameBox (мерцающее пламя+искры), colorBlock (плавная смена цвета вещества). §10/ЛО1: «Провести опыт» проигрывает анимацию по типу опыта (малахит зеленеет→чернеет, голубой осадок CuSO4+NaOH, синее пламя серы, пузырьки CO2). §11: при «Смешать» формируется осадок Cu(OH)2, весы остаются ровными. Тесты chem7: 16/16 pass; полный прогон 162/165 (3 — baseline Auth). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -325,17 +325,30 @@
|
||||
{ name: 'Горение серы', signs: ['выделение света и тепла (пламя)', 'появление резкого запаха'] },
|
||||
{ name: 'Добавление соды в уксус', signs: ['выделение газа (пузырьки)'] }
|
||||
];
|
||||
// анимация на каждый опыт (через Chem7Anim, CSS-хелперы)
|
||||
function demoAnim(idx, host) {
|
||||
var A = W.Chem7Anim; if (!A || !host) return null;
|
||||
if (idx === 0) return A.colorBlock(host, '#16a34a', '#1f2937', 'малахит → CuO + газы', 2000); // зелёный → чёрный
|
||||
if (idx === 1) return A.precipField(host, { color: '#38bdf8' }); // голубой осадок
|
||||
if (idx === 2) return A.flameBox(host, { color: '#3b82f6', sparks: true }); // синее пламя серы
|
||||
return A.bubbleField(host, { color: 'rgba(255,255,255,.85)' }); // пузырьки газа
|
||||
}
|
||||
function mount_signs(mountId) {
|
||||
var m = $(mountId); 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();
|
||||
m.innerHTML = '<div class="fld"><label>Опыт</label><select id="' + mountId + '-pick">'
|
||||
+ DEMOS.map(function (d, i) { return '<option value="' + i + '"' + (i === idx ? ' selected' : '') + '>' + esc(d.name) + '</option>'; }).join('') + '</select>'
|
||||
+ '<button class="btn primary" id="' + mountId + '-go">Провести опыт</button></div>'
|
||||
+ '<div id="' + mountId + '-stage" style="margin:8px 0"></div>'
|
||||
+ '<div class="out" id="' + mountId + '-out">Выбери опыт и нажми «Провести опыт».</div>';
|
||||
$(mountId + '-pick').addEventListener('change', function (e) { idx = +e.target.value; m._built = 0; render(); });
|
||||
$(mountId + '-pick').addEventListener('change', function (e) { idx = +e.target.value; render(); });
|
||||
$(mountId + '-go').addEventListener('click', function () {
|
||||
var d = DEMOS[idx], out = $(mountId + '-out'); out.className = 'out ok';
|
||||
var d = DEMOS[idx], out = $(mountId + '-out');
|
||||
stopAnim(); anim = demoAnim(idx, $(mountId + '-stage'));
|
||||
out.className = 'out ok';
|
||||
out.innerHTML = '<b>Наблюдаемые признаки реакции:</b><div style="margin-top:6px">'
|
||||
+ d.signs.map(function (s) { return '<div style="padding:5px 10px;margin:3px 0;border-radius:8px;background:var(--pri-soft);font-weight:600">✓ ' + esc(s) + '</div>'; }).join('')
|
||||
+ '</div><div style="font-size:.84rem;color:var(--muted);margin-top:6px">Эти признаки указывают, что произошла <b>химическая реакция</b> — образовались новые вещества.</div>';
|
||||
@@ -366,13 +379,17 @@
|
||||
+ '<text x="225" y="108" font-size="11" fill="var(--muted)">' + (mixed ? 'продукты' : 'реагенты') + '</text>'
|
||||
+ '</svg>';
|
||||
}
|
||||
var anim = null;
|
||||
function render() {
|
||||
if (anim) { anim.stop(); anim = null; }
|
||||
m.innerHTML = scale()
|
||||
+ '<div style="margin:6px 0;font-size:.92rem">' + (mixed
|
||||
? 'После реакции: <b>осадок Cu(OH)₂ + раствор Na₂SO₄</b>. Стрелка весов не сдвинулась — <b>масса сохранилась</b> (100 г = 100 г).'
|
||||
? 'После реакции: <b>осадок Cu(OH)₂ + раствор Na₂SO₄</b>. Стрелка весов <b>не сдвинулась</b> — масса сохранилась (100 г = 100 г).'
|
||||
: 'До реакции: <b>раствор CuSO₄ + раствор NaOH</b>, общая масса 100 г.') + '</div>'
|
||||
+ '<div id="p11-stage" style="margin:6px 0"></div>'
|
||||
+ '<button class="btn primary" id="p11-mix">' + (mixed ? 'Сбросить' : 'Смешать растворы') + '</button>';
|
||||
$('p11-mix').addEventListener('click', function () { mixed = !mixed; m._built = 0; render(); });
|
||||
if (mixed && W.Chem7Anim) anim = W.Chem7Anim.precipField($('p11-stage'), { color: '#38bdf8', h: 96 });
|
||||
$('p11-mix').addEventListener('click', function () { mixed = !mixed; render(); });
|
||||
}
|
||||
render();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user