diff --git a/backend/tests/math6-page.test.js b/backend/tests/math6-page.test.js
index 9fcce77..23a3df3 100644
--- a/backend/tests/math6-page.test.js
+++ b/backend/tests/math6-page.test.js
@@ -171,6 +171,8 @@ test('ch6: наглядная геометрия — интерактивы §1
test('анимации: canvas-демо монтируются (headless-safe)', async () => {
// Глава 6 §2: колесо + заметание площади
const r6 = await loadDom('math_6_ch6.html');
+ r6.doc.defaultView.goTo('p3'); await wait(100);
+ assert.ok(r6.doc.querySelector('#p3-tri svg polygon'), 'svg «перетаскиваемый треугольник» §6.3');
r6.doc.defaultView.goTo('p2'); await wait(100);
assert.ok(r6.doc.querySelector('#p2-roll canvas'), 'canvas «колесо» §6.2');
assert.ok(r6.doc.querySelector('#p2-sweep canvas'), 'canvas «заметание площади» §6.2');
diff --git a/frontend/js/math6_anim.js b/frontend/js/math6_anim.js
index 0c03784..e324568 100644
--- a/frontend/js/math6_anim.js
+++ b/frontend/js/math6_anim.js
@@ -540,6 +540,52 @@ M.constAreaRect = function (host, opts) {
return { stop: L.stop, set: function (w) { st.tw = w; } };
};
+/* ============================ ДЕМО 16: ПЕРЕТАСКИВАЕМЫЙ ТРЕУГОЛЬНИК (SVG) ============================ */
+M.triangleDrag = function (host, opts) {
+ var ns = 'http://www.w3.org/2000/svg', W0 = 300, H0 = 250;
+ host.innerHTML = '';
+ var svg = D.createElementNS(ns, 'svg'); svg.setAttribute('viewBox', '0 0 ' + W0 + ' ' + H0); svg.setAttribute('width', '100%');
+ svg.style.maxWidth = W0 + 'px'; svg.style.height = 'auto'; svg.style.touchAction = 'none'; svg.style.border = '1px solid var(--border,#e2e8f0)'; svg.style.borderRadius = '10px'; svg.style.background = 'var(--card,#fff)'; svg.style.display = 'block'; svg.style.margin = '0 auto';
+ host.appendChild(svg);
+ var label = D.createElement('div'); label.style.cssText = 'text-align:center;font-weight:700;color:var(--pri2,#3730a3);margin-top:8px;font-size:1.02rem'; host.appendChild(label);
+ var V = [{ x: 150, y: 40 }, { x: 55, y: 200 }, { x: 245, y: 200 }];
+ function dist(p, q) { return Math.hypot(p.x - q.x, p.y - q.y); }
+ function classify() {
+ var A = V[0], B = V[1], C = V[2], c = dist(A, B), a = dist(B, C), b = dist(C, A), arr = [a, b, c].slice().sort(function (x, y) { return x - y; }), eq = function (u, v) { return Math.abs(u - v) < 12; };
+ var side = (eq(a, b) && eq(b, c)) ? 'равносторонний' : ((eq(a, b) || eq(b, c) || eq(a, c)) ? 'равнобедренный' : 'разносторонний');
+ var mx = arr[2], rest = arr[0] * arr[0] + arr[1] * arr[1] - mx * mx, angle = Math.abs(rest) < 350 ? 'прямоугольный' : (rest > 0 ? 'остроугольный' : 'тупоугольный');
+ var rv = null; if (angle === 'прямоугольный') rv = (mx === a ? A : (mx === b ? B : C));
+ var ticks = []; if (side === 'равносторонний') ticks = [[A, B, 1], [B, C, 1], [C, A, 1]]; else if (side === 'равнобедренный') { if (eq(a, b)) ticks = [[B, C, 2], [C, A, 2]]; else if (eq(b, c)) ticks = [[C, A, 2], [A, B, 2]]; else ticks = [[A, B, 2], [B, C, 2]]; }
+ return { side: side, angle: angle, rv: rv, ticks: ticks };
+ }
+ function render() {
+ var info = classify(), A = V[0], B = V[1], C = V[2];
+ var s = '
Треугольник со сторонами $3$, $4$, $5$ называют «египетским» — строители Древнего Египта натягивали верёвку с 12 узлами (3+4+5) в виде треугольника, чтобы получить идеальный прямой угол для кладки стен пирамид. Этим приёмом пользуются строители до сих пор!
'); + h+='