feat(math6): живой график y=kx / y=k/x (Гл.5 §3) — плавное перетекание при k

Math6Anim.plotLive: canvas-плоскость с сеткой/осями; кривая плавно «перетекает»
(easing к целевому k). Переключатель прямая (y=kx, через начало) / обратная
(y=k/x, две ветви). Слайдер k (−4..4, шаг 0,5) двигает кривую вживую.
Вшито в Гл.5 §3 рядом со статичным графиком. Headless-safe. Тесты 19/19.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-02 21:33:47 +03:00
parent 61de12e2de
commit 1fc1672acd
3 changed files with 60 additions and 0 deletions
+15
View File
@@ -307,6 +307,11 @@ function buildP3(){
+'<div class="wg-help">Двигай коэффициент $k$ — смотри, как меняется наклон прямой.</div>'
+'<div class="sliders"><label>$k$ = <b id="p3-kv">2</b><input type="range" id="p3-k" min="-3" max="3" step="1" value="2"></label></div>'
+'<div id="p3-fig"></div></div>';
h+='<div class="wg" id="p3-live"><div class="wg-header"><span class="wg-badge">Анимация</span><div class="wg-title">Живой график: двигай k</div></div>'
+'<div class="wg-help">Переключай вид зависимости и двигай $k$ — график <b>плавно перетекает</b>. Прямая $y=kx$ всегда проходит через начало координат; гипербола $y=k/x$ — две ветви, через начало не проходит.</div>'
+'<div style="display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin-bottom:8px"><button class="btn primary" data-m="kx">прямая $y=kx$</button><button class="btn" data-m="kdx">обратная $y=k/x$</button></div>'
+'<div class="sliders"><label>$k$ = <b id="p3-lkv">2</b><input type="range" id="p3-lk" min="-4" max="4" step="0.5" value="2"></label></div>'
+'<div id="p3-livefig"></div></div>';
h+='<div class="wg" id="p3-iv2"><div class="wg-header"><span class="wg-badge">Интерактив 2</span><div class="wg-title">Прямая или обратная?</div></div>'
+'<div class="wg-help">Определи по графику вид зависимости.</div>'
+'<div class="score-display"><span>Вопрос <b id="p3-i">1</b> / 6</span><span>Очки: <b id="p3-s">0</b> / 6</span></div>'
@@ -322,6 +327,16 @@ function buildP3(){
h+=secNav('p2','app')+readBtn('p3');
box.innerHTML=h; renderMath(box);
(function(){
if(!window.Math6Anim) return;
var ctrl=Math6Anim.plotLive(document.getElementById('p3-livefig'),{k:2,mode:'kx'});
var sl=document.getElementById('p3-lk'), kv=document.getElementById('p3-lkv');
sl.oninput=function(){ var v=+sl.value; kv.textContent=String(v).replace('.',','); ctrl.setK(v); };
document.querySelectorAll('#p3-live [data-m]').forEach(function(b){ b.addEventListener('click',function(){
document.querySelectorAll('#p3-live [data-m]').forEach(function(x){x.classList.remove('primary');}); b.classList.add('primary');
ctrl.setMode(b.getAttribute('data-m')); }); });
})();
(function(){
var sl=document.getElementById('p3-k'), fig=document.getElementById('p3-fig');
function render(){ var k=+sl.value; document.getElementById('p3-kv').textContent=k;