fix(labs): SVG markup rendered as text in 6 simulations

Hardcoded inline <svg class="ic"> markers used as arrow replacements

(left over from emoji removal) were displayed as raw HTML text where

the consumer used textContent or canvas fillText:

- chemsandbox: csbar-v5 (Продукты cell) used textContent → SVG visible.

  Switched to innerHTML for consistency with eq/ionNet cells.

  Quiz question (qEl.textContent) and answer also receiving SVG —

  cleaned via _csClean at source.

- reactions: modeTxt drawn via canvas fillText — replaced SVG with →.

- ionexchange: REACTIONS data + canvas labels — bulk SVG → Unicode arrows.

- newton: action button labels used textContent → switched to innerHTML;

  canvas arrow labels: SVG → Unicode →/↓.

- collision: 'KE сохранена' canvas label — SVG checkmark → ✓.

- projectile: canvas badges + textContent wind label — SVG → Unicode ←/→/↩.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-05-17 10:47:50 +03:00
parent bf70c3d7d7
commit 6de91f7595
6 changed files with 44 additions and 42 deletions
+22 -22
View File
@@ -15,11 +15,11 @@ class IonExSim {
reacts: ['Ba²⁺', 'SO₄²⁻'],
spectators: ['Cl⁻', 'Na⁺'],
product: { f: 'BaSO₄', color: '#E0E0E0' },
mol: 'BaCl₂ + Na₂SO₄ <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> BaSO₄<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg> + 2NaCl',
full_ion: 'Ba²⁺ + 2Cl⁻ + 2Na⁺ + SO₄²⁻ <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> BaSO₄<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg> + 2Na⁺ + 2Cl⁻',
net_ion: 'Ba²⁺ + SO₄²⁻ <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> BaSO₄<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg>',
mol: 'BaCl₂ + Na₂SO₄ → BaSO₄↓ + 2NaCl',
full_ion: 'Ba²⁺ + 2Cl⁻ + 2Na⁺ + SO₄²⁻ → BaSO₄↓ + 2Na⁺ + 2Cl⁻',
net_ion: 'Ba²⁺ + SO₄²⁻ → BaSO₄↓',
type: 'precip', pcolor: '#E0E0E0', pname: 'BaSO₄ — белый осадок',
sign: '<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg>', signColor: '#E0E0E0',
sign: '', signColor: '#E0E0E0',
},
ag_cl: {
name: 'AgNO₃ + NaCl',
@@ -28,11 +28,11 @@ class IonExSim {
reacts: ['Ag⁺', 'Cl⁻'],
spectators: ['NO₃⁻', 'Na⁺'],
product: { f: 'AgCl', color: '#F5F5F5' },
mol: 'AgNO₃ + NaCl <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> AgCl<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg> + NaNO₃',
full_ion: 'Ag⁺ + NO₃⁻ + Na⁺ + Cl⁻ <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> AgCl<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg> + Na⁺ + NO₃⁻',
net_ion: 'Ag⁺ + Cl⁻ <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> AgCl<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg>',
mol: 'AgNO₃ + NaCl → AgCl↓ + NaNO₃',
full_ion: 'Ag⁺ + NO₃⁻ + Na⁺ + Cl⁻ → AgCl↓ + Na⁺ + NO₃⁻',
net_ion: 'Ag⁺ + Cl⁻ → AgCl↓',
type: 'precip', pcolor: '#F5F5F5', pname: 'AgCl — белый творожистый осадок',
sign: '<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg>', signColor: '#F5F5F5',
sign: '', signColor: '#F5F5F5',
},
co3_hcl: {
name: 'Na₂CO₃ + HCl',
@@ -40,12 +40,12 @@ class IonExSim {
right: [{ f: 'H⁺', color: '#EF5350', count: 10 }, { f: 'Cl⁻', color: '#AED581', count: 10 }],
reacts: ['CO₃²⁻', 'H⁺'],
spectators: ['Na⁺', 'Cl⁻'],
product: { f: 'CO₂<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="19" x2="12" y2="5"/><polyline points="5 12 12 5 19 12"/></svg>', color: '#B0BEC5' },
mol: 'Na₂CO₃ + 2HCl <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> 2NaCl + CO₂<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="19" x2="12" y2="5"/><polyline points="5 12 12 5 19 12"/></svg> + H₂O',
full_ion: '2Na⁺ + CO₃²⁻ + 2H⁺ + 2Cl⁻ <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> 2Na⁺ + 2Cl⁻ + CO₂<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="19" x2="12" y2="5"/><polyline points="5 12 12 5 19 12"/></svg> + H₂O',
net_ion: 'CO₃²⁻ + 2H⁺ <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> CO₂<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="19" x2="12" y2="5"/><polyline points="5 12 12 5 19 12"/></svg> + H₂O',
product: { f: 'CO₂', color: '#B0BEC5' },
mol: 'Na₂CO₃ + 2HCl → 2NaCl + CO₂↑ + H₂O',
full_ion: '2Na⁺ + CO₃²⁻ + 2H⁺ + 2Cl⁻ → 2Na⁺ + 2Cl⁻ + CO₂↑ + H₂O',
net_ion: 'CO₃²⁻ + 2H⁺ → CO₂↑ + H₂O',
type: 'gas', gcolor: '#B0BEC5', gname: 'CO₂ — углекислый газ',
sign: '<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="19" x2="12" y2="5"/><polyline points="5 12 12 5 19 12"/></svg>', signColor: '#B0BEC5',
sign: '', signColor: '#B0BEC5',
},
pb_i: {
name: 'Pb(NO₃)₂ + KI',
@@ -54,11 +54,11 @@ class IonExSim {
reacts: ['Pb²⁺', 'I⁻'],
spectators: ['NO₃⁻', 'K⁺'],
product: { f: 'PbI₂', color: '#F9A825' },
mol: 'Pb(NO₃)₂ + 2KI <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> PbI₂<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg> + 2KNO₃',
full_ion: 'Pb²⁺ + 2NO₃⁻ + 2K⁺ + 2I⁻ <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> PbI₂<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg> + 2K⁺ + 2NO₃⁻',
net_ion: 'Pb²⁺ + 2I⁻ <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> PbI₂<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg>',
mol: 'Pb(NO₃)₂ + 2KI → PbI₂↓ + 2KNO₃',
full_ion: 'Pb²⁺ + 2NO₃⁻ + 2K⁺ + 2I⁻ → PbI₂↓ + 2K⁺ + 2NO₃⁻',
net_ion: 'Pb²⁺ + 2I⁻ → PbI₂↓',
type: 'precip', pcolor: '#F9A825', pname: 'PbI₂ — ярко-жёлтый осадок',
sign: '<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg>', signColor: '#F9A825',
sign: '', signColor: '#F9A825',
},
ca_co3: {
name: 'CaCl₂ + Na₂CO₃',
@@ -67,11 +67,11 @@ class IonExSim {
reacts: ['Ca²⁺', 'CO₃²⁻'],
spectators: ['Cl⁻', 'Na⁺'],
product: { f: 'CaCO₃', color: '#F5F5F5' },
mol: 'CaCl₂ + Na₂CO₃ <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> CaCO₃<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg> + 2NaCl',
full_ion: 'Ca²⁺ + 2Cl⁻ + 2Na⁺ + CO₃²⁻ <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> CaCO₃<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg> + 2Na⁺ + 2Cl⁻',
net_ion: 'Ca²⁺ + CO₃²⁻ <svg class="ic" viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg> CaCO₃<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg>',
mol: 'CaCl₂ + Na₂CO₃ → CaCO₃↓ + 2NaCl',
full_ion: 'Ca²⁺ + 2Cl⁻ + 2Na⁺ + CO₃²⁻ → CaCO₃↓ + 2Na⁺ + 2Cl⁻',
net_ion: 'Ca²⁺ + CO₃²⁻ → CaCO₃↓',
type: 'precip', pcolor: '#F5F5F5', pname: 'CaCO₃ — белый осадок (мел)',
sign: '<svg class="ic" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg>', signColor: '#F5F5F5',
sign: '', signColor: '#F5F5F5',
},
};
@@ -466,7 +466,7 @@ class IonExSim {
ctx.fillStyle = rxn.signColor; ctx.font = 'bold 10px monospace';
ctx.textAlign = 'right'; ctx.textBaseline = 'top';
ctx.shadowColor = rxn.signColor; ctx.shadowBlur = 8;
const label = rxn.type === 'precip' ? `<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg> ${rxn.sign} осадок` : `<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg> ${rxn.sign} газ`;
const label = rxn.type === 'precip' ? `${rxn.sign} осадок` : ` ${rxn.sign} газ`;
ctx.fillText(label, W - 14, py + 3);
ctx.restore();
}