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:
@@ -1585,7 +1585,7 @@ class ChemSandboxSim {
|
||||
if (rx.fx.gas) {
|
||||
questions.push(`Получи газ ${rx.fx.gas}`);
|
||||
}
|
||||
questions.push(`Проведи реакцию: ${prods}`);
|
||||
questions.push(`Проведи реакцию: ${_csClean(prods)}`);
|
||||
if (rx.type === 'Нейтрализация') {
|
||||
questions.push('Проведи реакцию нейтрализации');
|
||||
}
|
||||
@@ -1622,7 +1622,7 @@ class ChemSandboxSim {
|
||||
score: this._quizScore,
|
||||
total: this._quizTotal,
|
||||
result: this._quizResult,
|
||||
answer: this._quizTask ? this._quizTask.rx.eq : null,
|
||||
answer: this._quizTask ? _csClean(this._quizTask.rx.eq) : null,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1821,7 +1821,9 @@ class ChemSandboxSim {
|
||||
const eqEl = document.getElementById('csbar-v4');
|
||||
eqEl.innerHTML = info.equation || '—';
|
||||
eqEl.title = (info.equation || '').replace(/<[^>]*>/g, '');
|
||||
document.getElementById('csbar-v5').textContent = info.products || '—';
|
||||
const prodEl = document.getElementById('csbar-v5');
|
||||
prodEl.innerHTML = info.products || '—';
|
||||
prodEl.title = (info.products || '').replace(/<[^>]*>/g, '');
|
||||
const ionEl = document.getElementById('csbar-v6');
|
||||
ionEl.innerHTML = info.ionNet || '—';
|
||||
ionEl.title = (info.ionNet || '').replace(/<[^>]*>/g, '');
|
||||
|
||||
@@ -709,7 +709,7 @@ class CollisionSim {
|
||||
ctx.fillText(label, ix, iy);
|
||||
} else if (lossPct === 0 && keBefore > 0.1) {
|
||||
const ix = this._impactPt.x, iy = this._impactPt.y - 42;
|
||||
const label = 'KE сохранена <svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>';
|
||||
const label = 'KE сохранена ✓';
|
||||
ctx.font = 'bold 10px Manrope';
|
||||
const tw = ctx.measureText(label).width;
|
||||
ctx.fillStyle = 'rgba(123,245,164,.15)';
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ class NewtonSim {
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Физика I-B : орбита <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> прямолинейное движение ────────── */
|
||||
/* ── Физика I-B : орбита → прямолинейное движение ────────── */
|
||||
|
||||
_step1B(dt) {
|
||||
const s = this._1B;
|
||||
@@ -804,10 +804,10 @@ class NewtonSim {
|
||||
const alpha = Math.min(1, s.forceFlash * 2.5);
|
||||
const fScale = 72 * alpha;
|
||||
const ny = g.gY - CH - 32;
|
||||
/* Сила на ядро <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> вправо */
|
||||
this._arrow(ctx, s.cx + CW / 2 + 20, ny, s.cx + CW / 2 + 20 + fScale, ny, '#EF476F', 'F<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>ядро', 2.5);
|
||||
/* Реакция на пушку <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> влево */
|
||||
this._arrow(ctx, s.cx - CW / 2 - 20, ny, s.cx - CW / 2 - 20 - fScale, ny, '#4CC9F0', 'F<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>пушка', 2.5);
|
||||
/* Сила на ядро → вправо */
|
||||
this._arrow(ctx, s.cx + CW / 2 + 20, ny, s.cx + CW / 2 + 20 + fScale, ny, '#EF476F', 'F→ядро', 2.5);
|
||||
/* Реакция на пушку → влево */
|
||||
this._arrow(ctx, s.cx - CW / 2 - 20, ny, s.cx - CW / 2 - 20 - fScale, ny, '#4CC9F0', 'F→пушка', 2.5);
|
||||
|
||||
ctx.save(); ctx.globalAlpha = alpha;
|
||||
ctx.font = 'bold 12px sans-serif'; ctx.fillStyle = '#FFD166';
|
||||
@@ -990,7 +990,7 @@ class NewtonSim {
|
||||
}
|
||||
/* Falling after fuel out — show gravity arrow */
|
||||
if (s.fuel <= 0 && !s.stopped) {
|
||||
this._arrow(ctx, rx, ry + 25, rx, ry + 65, '#EF476F', 'mg<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>', 2.5);
|
||||
this._arrow(ctx, rx, ry + 25, rx, ry + 65, '#EF476F', 'mg↓', 2.5);
|
||||
ctx.font = 'bold 13px sans-serif'; ctx.fillStyle = '#EF476F';
|
||||
ctx.textAlign = 'center'; ctx.fillText('Топливо кончилось — ракета падает!', W / 2, H * 0.15); ctx.textAlign = 'left';
|
||||
}
|
||||
@@ -1009,7 +1009,7 @@ class NewtonSim {
|
||||
ctx.textAlign = 'center'; ctx.fillText('Нажмите «Запуск» для включения двигателя', W / 2, H * 0.50); ctx.textAlign = 'left';
|
||||
}
|
||||
|
||||
this._caption(ctx, 'Газ вниз <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> ракета вверх\n(3-й закон Ньютона)', W, H);
|
||||
this._caption(ctx, 'Газ вниз → ракета вверх\n(3-й закон Ньютона)', W, H);
|
||||
}
|
||||
|
||||
/* ── Вспомогательные рисовалки ──────────────────────────── */
|
||||
@@ -1350,8 +1350,8 @@ function _nwt_lighten(hex, d) {
|
||||
|
||||
// action button label
|
||||
const lbl = sceneData.action || (law === 1 ? '<svg class="ic" viewBox="0 0 24 24"><circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><line x1="20" y1="4" x2="8.12" y2="15.88"/><line x1="14.47" y1="14.48" x2="20" y2="20"/><line x1="8.12" y1="8.12" x2="12" y2="12"/></svg> Нить' : '<svg class="ic" viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg> Действие');
|
||||
document.getElementById('newton-action-label').textContent = lbl;
|
||||
document.getElementById('newton-action-top').textContent = lbl;
|
||||
document.getElementById('newton-action-label').innerHTML = lbl;
|
||||
document.getElementById('newton-action-top').innerHTML = lbl;
|
||||
|
||||
// show/hide sliders
|
||||
document.getElementById('newton-mu-block').style.display = law === 1 && scene === 'A' ? '' : 'none';
|
||||
|
||||
@@ -147,8 +147,8 @@ class ProjectileSim {
|
||||
}
|
||||
}
|
||||
const st = this.stats();
|
||||
const windStr = this.wind !== 0 ? ` <svg class="ic" viewBox="0 0 24 24"><path d="M17.7 7.7a2.5 2.5 0 1 1 1.8 4.3H2"/><path d="M9.6 4.6A2 2 0 1 1 11 8H2"/><path d="M12.6 19.4A2 2 0 1 0 14 16H2"/></svg>${this.wind > 0 ? '+' : ''}${this.wind}` : '';
|
||||
const label = `${this.angle}° ${this.v0}м/с${windStr}${this.drag ? ' +drag' : ''}${this.bounce ? ' <svg class="ic" viewBox="0 0 24 24"><polyline points="9 14 4 9 9 4"/><path d="M20 20v-7a4 4 0 0 0-4-4H4"/></svg>' : ''}`;
|
||||
const windStr = this.wind !== 0 ? ` ветер ${this.wind > 0 ? '+' : ''}${this.wind}` : '';
|
||||
const label = `${this.angle}° ${this.v0}м/с${windStr}${this.drag ? ' +drag' : ''}${this.bounce ? ' ↩' : ''}`;
|
||||
const color = this._GHOST_COLORS[this._ghostIdx % this._GHOST_COLORS.length];
|
||||
this._ghostIdx++;
|
||||
this._ghosts.push({ points, color, label, range: st.range, hMax: st.hMax });
|
||||
@@ -811,12 +811,12 @@ class ProjectileSim {
|
||||
bRight -= 130;
|
||||
}
|
||||
if (this.wind !== 0) {
|
||||
const dir = this.wind > 0 ? '<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>' : '<svg class="ic" viewBox="0 0 24 24"><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></svg>';
|
||||
const dir = this.wind > 0 ? '→' : '←';
|
||||
this._drawBadge(ctx, bRight, PT + 6, dir + ' ветер ' + Math.abs(this.wind) + 'м/с', 'rgba(6,214,224,.12)', 'rgba(6,214,224,.8)');
|
||||
bRight -= 130;
|
||||
}
|
||||
if (this.bounce) {
|
||||
this._drawBadge(ctx, bRight, PT + 6, '<svg class="ic" viewBox="0 0 24 24"><polyline points="9 14 4 9 9 4"/><path d="M20 20v-7a4 4 0 0 0-4-4H4"/></svg> e=' + this.restitution.toFixed(2), 'rgba(123,245,164,.1)', 'rgba(123,245,164,.75)');
|
||||
this._drawBadge(ctx, bRight, PT + 6, '↩ e=' + this.restitution.toFixed(2), 'rgba(123,245,164,.1)', 'rgba(123,245,164,.75)');
|
||||
}
|
||||
|
||||
/* speed badge bottom-right */
|
||||
@@ -1077,7 +1077,7 @@ function _projArrow(ctx, x1, y1, x2, y2, color, lw) {
|
||||
pSim.onPlayPause = projPlayPause;
|
||||
}
|
||||
pSim.fit();
|
||||
projParam(); // sync sliders <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> sim
|
||||
projParam(); // sync sliders → sim
|
||||
pSim.draw();
|
||||
_projUpdateUI(pSim.stats());
|
||||
}));
|
||||
@@ -1187,7 +1187,7 @@ function _projArrow(ctx, x1, y1, x2, y2, color, lw) {
|
||||
|
||||
function projWindChange() {
|
||||
const wind = +document.getElementById('sl-wind').value;
|
||||
const label = wind === 0 ? '0 м/с' : (wind > 0 ? '<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> +' : '<svg class="ic" viewBox="0 0 24 24"><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></svg> ') + Math.abs(wind) + ' м/с';
|
||||
const label = wind === 0 ? '0 м/с' : (wind > 0 ? '→ +' : '← ') + Math.abs(wind) + ' м/с';
|
||||
document.getElementById('p-wind').textContent = label;
|
||||
document.getElementById('ps-loss-wrap').style.display = wind !== 0 ? '' : (pSim && pSim.drag ? '' : 'none');
|
||||
if (pSim) { pSim.setParams({ wind }); _projSyncPlayBtn(); }
|
||||
|
||||
@@ -564,7 +564,7 @@ class ReactionSim {
|
||||
ctx.fillText('C', ex + ew, toY(pE) - 4);
|
||||
|
||||
// Mode label at bottom
|
||||
const modeTxt = { forward: '<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> A + B <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> C', reversible: '⇌ A + B ⇌ C', chain: 'цепная реакция' }[this.mode] || '';
|
||||
const modeTxt = { forward: '→ A + B → C', reversible: '⇌ A + B ⇌ C', chain: 'цепная реакция' }[this.mode] || '';
|
||||
ctx.fillStyle = 'rgba(255,255,255,0.22)';
|
||||
ctx.font = '8px sans-serif';
|
||||
ctx.textAlign = 'center';
|
||||
|
||||
Reference in New Issue
Block a user