feat(trigcircle): Фаза 1 — работа с углами + обзор (тренажёр тригонометрии)
План тренажёра в plans/trig-circle/PLAN.md (всё по теме на окружности, кроме графиков функций). Фаза 1 (аддитивно к рабочему режиму): - Ввод угла в градусах (поле + Enter/кнопка) → goToAngle (нормализует, показывает котерминальность). Подсказка «+360°·k» в бейдже угла. - Тумблер «График/функции» — скрыть график (тема «функции») → круг на всю ширину (переиспользует существующий слой graph + _layout). - Полная сетка табличных углов (16: 0…330°) вместо 8. - Опорный (острый) угол к оси Ox в выводе (основа формул приведения) + знаки sin/cos/tg по текущей четверти. stats() расширен полями refAngle/refDeg. Verified: node --check; headless-смоук (vm + canvas-Proxy) 9/9 — опорный угол 30/150/210→30°, 300→60°, 90→90°, 0→0; знаки по четвертям (II: sin+ cos− tg−; IV: sin− cos+); новые глобальные glue-функции определены. Эмодзи нет (стрелка — inline SVG .ic, tg-неопр. — em-dash). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -130,7 +130,16 @@ class TrigCircleSim {
|
||||
const ct = Math.abs(s) > 1e-9 ? co / s : undefined;
|
||||
const deg = a * 180 / Math.PI;
|
||||
const q = a < Math.PI/2 ? 1 : a < Math.PI ? 2 : a < 3*Math.PI/2 ? 3 : 4;
|
||||
return { angle: a, deg, radLabel: this._radLbl(a), sin: s, cos: co, tan: t, cot: ct, quadrant: q };
|
||||
// Опорный (острый) угол — к ближайшей оси Ox: основа формул приведения.
|
||||
let ref;
|
||||
if (a <= Math.PI / 2) ref = a;
|
||||
else if (a <= Math.PI) ref = Math.PI - a;
|
||||
else if (a <= 3 * Math.PI/2) ref = a - Math.PI;
|
||||
else ref = 2 * Math.PI - a;
|
||||
return {
|
||||
angle: a, deg, radLabel: this._radLbl(a), sin: s, cos: co, tan: t, cot: ct, quadrant: q,
|
||||
refAngle: ref, refDeg: ref * 180 / Math.PI,
|
||||
};
|
||||
}
|
||||
|
||||
/* ═══ Layout ═══════════════════════════════════════════════════════ */
|
||||
@@ -1029,6 +1038,26 @@ if (typeof window !== 'undefined') window.TrigCircleSim = TrigCircleSim;
|
||||
if (window.LabFX) LabFX.sound.play('click');
|
||||
}
|
||||
|
||||
/* Ввод угла в градусах (поле + Enter/кнопка). Принимает любое число (включая <0 и >360),
|
||||
goToAngle нормализует — заодно демонстрирует котерминальность. */
|
||||
function trigSetAngleDeg(inp) {
|
||||
if (!trigSim || !inp) return;
|
||||
const v = parseFloat(String(inp.value || '').replace(',', '.'));
|
||||
if (!isFinite(v)) return;
|
||||
trigSim.goToAngle(v * Math.PI / 180);
|
||||
}
|
||||
function trigAngleKey(e, inp) { if (e && (e.key === 'Enter' || e.keyCode === 13)) trigSetAngleDeg(inp); }
|
||||
|
||||
/* Показать/скрыть график функций (тема «функции» — по умолчанию можно убрать,
|
||||
круг займёт всю ширину). Переиспользует существующий слой 'graph'. */
|
||||
function trigToggleGraph(rowEl) {
|
||||
if (!trigSim) return;
|
||||
const on = rowEl.classList.toggle('active');
|
||||
trigSim.toggleLayer('graph', on);
|
||||
const fns = document.getElementById('trig-graph-fns');
|
||||
if (fns) fns.style.display = on ? '' : 'none';
|
||||
}
|
||||
|
||||
function _trigUpdateUI(s) {
|
||||
const _f = v => {
|
||||
if (v === undefined) return '—';
|
||||
@@ -1050,9 +1079,22 @@ if (typeof window !== 'undefined') window.TrigCircleSim = TrigCircleSim;
|
||||
document.getElementById('trig-v-tan').textContent = _f(s.tan);
|
||||
document.getElementById('trig-v-cot').textContent = _f(s.cot);
|
||||
|
||||
// Angle badge
|
||||
// Angle badge + котерминальные углы (+360°·k)
|
||||
document.getElementById('trig-angle-badge').innerHTML =
|
||||
`${degStr} = ${s.radLabel}<br><span style="font-size:0.72rem;opacity:0.6">${s.angle.toFixed(4)} рад</span>`;
|
||||
`${degStr} = ${s.radLabel}<br><span style="font-size:0.72rem;opacity:0.6">${s.angle.toFixed(4)} рад</span>` +
|
||||
`<br><span style="font-size:0.68rem;opacity:0.5">+ 360°·k (котерминальные)</span>`;
|
||||
|
||||
// Опорный (острый) угол — guarded (панель может не иметь элемента)
|
||||
const refEl = document.getElementById('trig-ref');
|
||||
if (refEl) refEl.textContent = (Math.round(s.refDeg * 10) / 10) + '°';
|
||||
// Знаки функций в текущей четверти
|
||||
const signsEl = document.getElementById('trig-signs');
|
||||
if (signsEl) {
|
||||
const sg = v => (v > 1e-9 ? '+' : v < -1e-9 ? '−' : '0');
|
||||
signsEl.innerHTML =
|
||||
`<b style="color:#EF476F">sin ${sg(s.sin)}</b> · <b style="color:#06D6E0">cos ${sg(s.cos)}</b> · ` +
|
||||
`<b style="color:#FFD166">tg ${s.tan === undefined ? '—' : sg(s.tan)}</b>`;
|
||||
}
|
||||
|
||||
// Stats bar (nice fractions)
|
||||
document.getElementById('trigbar-angle').textContent = degStr;
|
||||
|
||||
Reference in New Issue
Block a user