fix(geom9 ch1): переделаны рисунки в §1 и §3
§1 IV1 «Конструктор прямоугольного треугольника»: - Стандартное расположение: прямой угол справа-снизу (C), угол α при A слева-снизу, гипотенуза диагональю - Цветовая кодировка сторон: гипотенуза c фиолетовая, противолежащий a красный, прилежащий b синий - Подписи в реальных единицах (c = 10), а не px/22 - Легенда с обозначением каждой стороны - Под графиком — формулы $\sin = a/c$, $\cos = b/c$ итд §3 IV1 «Два эталонных треугольника» (бывшая «Три»): - Поправлен заголовок: было «Три», нарисовано два - Оба треугольника в стандартном расположении - Помощник drawTri() — единая логика для обоих - Углы 30°/60° (красный/голубой) для 30-60-90, 45°/45° для равнобедренного Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -644,69 +644,77 @@ function buildP1(){
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
|
||||
/* IV1 — слайдер + SVG */
|
||||
/* IV1 — слайдер + SVG (стандартное расположение: прямой угол справа-снизу, угол α при A) */
|
||||
(function(){
|
||||
const sl = document.getElementById('p1-iv1-a');
|
||||
const lab = document.getElementById('p1-iv1-aval');
|
||||
const svg = document.getElementById('p1-iv1-svg');
|
||||
const out = document.getElementById('p1-iv1-out');
|
||||
const seen = new Set();
|
||||
// Цвета сторон: гипотенуза — фиолетовая, противолежащий α — красный, прилежащий — синий.
|
||||
const COL_HYP = '#7c3aed', COL_OPP = '#dc2626', COL_ADJ = '#2563eb';
|
||||
function draw(){
|
||||
const aDeg = +sl.value;
|
||||
lab.textContent = aDeg;
|
||||
const aRad = deg2rad(aDeg);
|
||||
const c = 220; // гипотенуза в пикселях
|
||||
// Геометрические вершины: A (внизу слева), B (верх — прямой угол), C (внизу справа).
|
||||
// Прямой угол при B. Угол α при C.
|
||||
// BC = c·cos α (горизонтальный катет, прилежащий к α)
|
||||
// AB = c·sin α (вертикальный катет, противолежащий α)
|
||||
const BCpx = c * Math.cos(aRad);
|
||||
const ABpx = c * Math.sin(aRad);
|
||||
const cx = 60, cyBase = 270; // позиция A
|
||||
const A = {x: cx, y: cyBase};
|
||||
const C = {x: cx + BCpx, y: cyBase};
|
||||
const B = {x: cx, y: cyBase - ABpx};
|
||||
// Внутренние векторы в B (прямой угол): по BA — вниз, по BC — вправо-вниз
|
||||
const uBA = unitVec(B, A);
|
||||
const uBC = unitVec(B, C);
|
||||
const uCA = unitVec(C, A); // вдоль гипотенузы из C
|
||||
const uCB = unitVec(C, B); // вдоль катета из C
|
||||
// Целые «единицы» для подписи: гипотенуза c = 10.
|
||||
const cUnits = 10;
|
||||
const aUnits = +(cUnits * Math.sin(aRad)).toFixed(2); // противолежащий α
|
||||
const bUnits = +(cUnits * Math.cos(aRad)).toFixed(2); // прилежащий α
|
||||
// Масштаб px на единицу подбираем так, чтобы прилежащий катет вписался в ~300 px.
|
||||
const px = 26;
|
||||
// Стандартное расположение:
|
||||
// A — нижний левый угол (вершина с углом α).
|
||||
// C — нижний правый угол (прямой угол).
|
||||
// B — верхний правый угол.
|
||||
// Гипотенуза = AB (диагональ), прилежащий к α = AC (горизонталь), противолежащий = BC (вертикаль).
|
||||
const A = {x: 60, y: 280};
|
||||
const C = {x: 60 + bUnits * px, y: 280};
|
||||
const B = {x: C.x, y: 280 - aUnits * px};
|
||||
// Векторы внутрь треугольника
|
||||
const uCA = unitVec(C, A), uCB = unitVec(C, B); // прямой угол в C
|
||||
const uAC = unitVec(A, C), uAB = unitVec(A, B); // острый α в A
|
||||
let s = '';
|
||||
// фон
|
||||
s += '<rect x="0" y="0" width="400" height="320" fill="none"/>';
|
||||
// треугольник
|
||||
s += '<polygon points="'+A.x+','+A.y+' '+B.x+','+B.y+' '+C.x+','+C.y+'" fill="rgba(217,119,6,.08)" stroke="#b45309" stroke-width="2.2" stroke-linejoin="round"/>';
|
||||
// маркер прямого угла в B (внутренние векторы — uBA и uBC)
|
||||
s += '<polyline points="'+rightAngleMark(B, uBA, uBC, 12)+'" fill="none" stroke="#0f172a" stroke-width="1.8"/>';
|
||||
// дуга угла α при C (от CA к CB)
|
||||
s += '<path d="'+angleArcAuto(C, uCA, uCB, 30)+'" fill="none" stroke="#dc2626" stroke-width="2"/>';
|
||||
// Стороны как отдельные линии разных цветов
|
||||
s += '<polygon points="'+A.x+','+A.y+' '+C.x+','+C.y+' '+B.x+','+B.y+'" fill="rgba(217,119,6,.07)" stroke="none"/>';
|
||||
s += '<line x1="'+A.x+'" y1="'+A.y+'" x2="'+C.x+'" y2="'+C.y+'" stroke="'+COL_ADJ+'" stroke-width="3" stroke-linecap="round"/>';
|
||||
s += '<line x1="'+C.x+'" y1="'+C.y+'" x2="'+B.x+'" y2="'+B.y+'" stroke="'+COL_OPP+'" stroke-width="3" stroke-linecap="round"/>';
|
||||
s += '<line x1="'+A.x+'" y1="'+A.y+'" x2="'+B.x+'" y2="'+B.y+'" stroke="'+COL_HYP+'" stroke-width="3" stroke-linecap="round"/>';
|
||||
// маркер прямого угла в C
|
||||
s += '<polyline points="'+rightAngleMark(C, uCA, uCB, 14)+'" fill="none" stroke="#0f172a" stroke-width="1.8"/>';
|
||||
// дуга угла α при A
|
||||
s += '<path d="'+angleArcAuto(A, uAC, uAB, 34)+'" fill="none" stroke="#dc2626" stroke-width="2.2"/>';
|
||||
// подпись α
|
||||
const aMid = {x: C.x + 44*Math.cos(Math.atan2((uCA.y+uCB.y)/2,(uCA.x+uCB.x)/2)), y: C.y + 44*Math.sin(Math.atan2((uCA.y+uCB.y)/2,(uCA.x+uCB.x)/2))};
|
||||
s += '<text x="'+aMid.x+'" y="'+aMid.y+'" text-anchor="middle" dominant-baseline="middle" font-family="Inter,sans-serif" font-size="15" font-weight="700" fill="#dc2626">α</text>';
|
||||
const midDir = {x:(uAC.x+uAB.x)/2, y:(uAC.y+uAB.y)/2};
|
||||
const midLen = Math.sqrt(midDir.x*midDir.x+midDir.y*midDir.y) || 1;
|
||||
const aLab = {x: A.x + 50*midDir.x/midLen, y: A.y + 50*midDir.y/midLen};
|
||||
s += '<text x="'+aLab.x+'" y="'+aLab.y+'" text-anchor="middle" dominant-baseline="middle" font-family="Inter,sans-serif" font-size="16" font-weight="800" fill="#dc2626">α</text>';
|
||||
// вершины
|
||||
s += '<circle cx="'+A.x+'" cy="'+A.y+'" r="4" fill="#0f172a"/>';
|
||||
s += '<circle cx="'+B.x+'" cy="'+B.y+'" r="4" fill="#0f172a"/>';
|
||||
s += '<circle cx="'+C.x+'" cy="'+C.y+'" r="4" fill="#0f172a"/>';
|
||||
s += '<text x="'+(A.x-12)+'" y="'+(A.y+18)+'" text-anchor="end" font-family="Inter,sans-serif" font-size="16" font-weight="700" fill="#0f172a">A</text>';
|
||||
s += '<text x="'+(B.x-12)+'" y="'+(B.y-4)+'" text-anchor="end" font-family="Inter,sans-serif" font-size="16" font-weight="700" fill="#0f172a">B</text>';
|
||||
s += '<text x="'+(C.x+12)+'" y="'+(C.y+18)+'" text-anchor="start" font-family="Inter,sans-serif" font-size="16" font-weight="700" fill="#0f172a">C</text>';
|
||||
// подписи сторон
|
||||
const labBC = 'BC='+(BCpx/22).toFixed(2);
|
||||
const labAB = 'AB='+(ABpx/22).toFixed(2);
|
||||
const labAC = 'AC='+(c/22).toFixed(2);
|
||||
s += '<text x="'+((B.x+C.x)/2)+'" y="'+(cyBase+34)+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="12" fill="#b45309">'+labBC+'</text>';
|
||||
s += '<text x="'+(B.x-32)+'" y="'+((A.y+B.y)/2)+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="12" fill="#b45309">'+labAB+'</text>';
|
||||
// подпись гипотенузы — поднимем над линией AC
|
||||
const midAC = {x:(A.x+C.x)/2, y:(A.y+C.y)/2};
|
||||
const nAC = {x:-(C.y-A.y), y:(C.x-A.x)};
|
||||
const nL = Math.sqrt(nAC.x*nAC.x+nAC.y*nAC.y)||1;
|
||||
const labP = {x: midAC.x + 16*nAC.x/nL, y: midAC.y + 16*nAC.y/nL};
|
||||
s += '<text x="'+labP.x+'" y="'+labP.y+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="12" fill="#b45309">'+labAC+'</text>';
|
||||
[A,B,C].forEach(P=>{ s+='<circle cx="'+P.x+'" cy="'+P.y+'" r="4" fill="#0f172a"/>'; });
|
||||
s += '<text x="'+(A.x-14)+'" y="'+(A.y+6)+'" text-anchor="end" font-family="Inter,sans-serif" font-size="16" font-weight="800" fill="#0f172a">A</text>';
|
||||
s += '<text x="'+(B.x+14)+'" y="'+(B.y+4)+'" text-anchor="start" font-family="Inter,sans-serif" font-size="16" font-weight="800" fill="#0f172a">B</text>';
|
||||
s += '<text x="'+(C.x+14)+'" y="'+(C.y+18)+'" text-anchor="start" font-family="Inter,sans-serif" font-size="16" font-weight="800" fill="#0f172a">C</text>';
|
||||
// длина прилежащего катета AC
|
||||
s += '<text x="'+((A.x+C.x)/2)+'" y="'+(A.y+24)+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="13" font-weight="700" fill="'+COL_ADJ+'">b = '+bUnits.toFixed(2)+'</text>';
|
||||
// длина противолежащего BC
|
||||
s += '<text x="'+(C.x+18)+'" y="'+((B.y+C.y)/2+5)+'" text-anchor="start" font-family="JetBrains Mono,monospace" font-size="13" font-weight="700" fill="'+COL_OPP+'">a = '+aUnits.toFixed(2)+'</text>';
|
||||
// длина гипотенузы AB — над линией
|
||||
const midAB = {x:(A.x+B.x)/2, y:(A.y+B.y)/2};
|
||||
const nAB = {x:-(B.y-A.y), y:(B.x-A.x)};
|
||||
const nL = Math.sqrt(nAB.x*nAB.x+nAB.y*nAB.y)||1;
|
||||
const labHyp = {x: midAB.x - 22*nAB.x/nL, y: midAB.y - 22*nAB.y/nL};
|
||||
s += '<text x="'+labHyp.x+'" y="'+labHyp.y+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="13" font-weight="700" fill="'+COL_HYP+'">c = '+cUnits+'</text>';
|
||||
// легенда
|
||||
s += '<g font-family="Inter,sans-serif" font-size="11" font-weight="600">';
|
||||
s += '<rect x="14" y="14" width="14" height="3" fill="'+COL_HYP+'"/><text x="34" y="20" fill="#0f172a">гипотенуза c</text>';
|
||||
s += '<rect x="14" y="32" width="14" height="3" fill="'+COL_OPP+'"/><text x="34" y="38" fill="#0f172a">противолежащий a</text>';
|
||||
s += '<rect x="14" y="50" width="14" height="3" fill="'+COL_ADJ+'"/><text x="34" y="56" fill="#0f172a">прилежащий b</text>';
|
||||
s += '</g>';
|
||||
svg.innerHTML = s;
|
||||
// числовые значения
|
||||
const sn = Math.sin(aRad), cs = Math.cos(aRad), tn = Math.tan(aRad), ct = 1/Math.tan(aRad);
|
||||
out.innerHTML = '$\\sin '+aDeg+'^\\circ \\approx '+sn.toFixed(3)+'$ · $\\cos '+aDeg+'^\\circ \\approx '+cs.toFixed(3)+'$<br>'
|
||||
+ '$\\tan '+aDeg+'^\\circ \\approx '+tn.toFixed(3)+'$ · $\\cot '+aDeg+'^\\circ \\approx '+ct.toFixed(3)+'$';
|
||||
out.innerHTML = '$\\sin '+aDeg+'^\\circ = \\dfrac{a}{c} \\approx '+sn.toFixed(3)+'$ · $\\cos '+aDeg+'^\\circ = \\dfrac{b}{c} \\approx '+cs.toFixed(3)+'$<br>'
|
||||
+ '$\\tan '+aDeg+'^\\circ = \\dfrac{a}{b} \\approx '+tn.toFixed(3)+'$ · $\\cot '+aDeg+'^\\circ = \\dfrac{b}{a} \\approx '+ct.toFixed(3)+'$';
|
||||
renderMath(out);
|
||||
seen.add(aDeg);
|
||||
if(seen.size >= 6 && !seen.has('done')){ addXp(10,'p1-iv1'); bumpProgress('p1', 15); seen.add('done'); }
|
||||
@@ -1231,8 +1239,8 @@ function buildP3(){
|
||||
|
||||
/* IV1 — Три эталонных треугольника */
|
||||
html += `<div class="wg" id="p3-iv1">
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Три эталонных треугольника</div></div>
|
||||
<div class="wg-help">Слева — треугольник $30^\\circ\\text{-}60^\\circ\\text{-}90^\\circ$ (катеты $1$ и $\\sqrt{3}$, гипотенуза $2$). Справа — равнобедренный $45^\\circ\\text{-}45^\\circ\\text{-}90^\\circ$ (катеты $1$, гипотенуза $\\sqrt{2}$).</div>
|
||||
<div class="wg-header"><span class="wg-badge">ИНТЕРАКТИВ 1</span><div class="wg-title">Два эталонных треугольника</div></div>
|
||||
<div class="wg-help">Слева — треугольник $30^\\circ\\text{-}60^\\circ\\text{-}90^\\circ$ (катеты $1$ и $\\sqrt{3}$, гипотенуза $2$): из него читаются значения для $30^\\circ$ и $60^\\circ$. Справа — равнобедренный $45^\\circ\\text{-}45^\\circ\\text{-}90^\\circ$ (катеты $1$, гипотенуза $\\sqrt{2}$): из него — значения для $45^\\circ$.</div>
|
||||
<div style="background:var(--card);border-radius:10px;padding:10px;overflow-x:auto">
|
||||
<svg id="p3-iv1-svg" viewBox="0 0 600 220" style="width:100%;min-width:420px;height:auto;display:block"></svg>
|
||||
</div>
|
||||
@@ -1304,82 +1312,77 @@ function buildP3(){
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
|
||||
/* IV1 — рисуем три эталонных треугольника */
|
||||
/* IV1 — Два эталонных треугольника (стандартное расположение: прямой угол справа-снизу) */
|
||||
(function(){
|
||||
const svg = document.getElementById('p3-iv1-svg');
|
||||
if(!svg) return;
|
||||
let s = '';
|
||||
// Треугольник 30-60-90: катеты 1 и sqrt(3), гипотенуза 2. Используем масштаб 60 px = 1 ед.
|
||||
// Левый: BC = sqrt(3) (горизонт., прилежащий 30°), AB = 1 (вертикальный, противолежащий 30°)
|
||||
// Вершины: A слева внизу, B слева вверху (прямой угол), C справа внизу.
|
||||
// Угол 30° при C, угол 60° при A.
|
||||
(function(){
|
||||
const u = 60;
|
||||
const Ax = 40, Ay = 180;
|
||||
const A = {x: Ax, y: Ay};
|
||||
const B = {x: Ax, y: Ay - u}; // катет AB = 1
|
||||
const C = {x: Ax + Math.sqrt(3)*u, y: Ay}; // катет BC = sqrt(3)
|
||||
const uBA = unitVec(B, A);
|
||||
const uBC = unitVec(B, C);
|
||||
const uCA = unitVec(C, A);
|
||||
const uCB = unitVec(C, B);
|
||||
const uAB = unitVec(A, B);
|
||||
const uAC = unitVec(A, C);
|
||||
s += '<polygon points="'+A.x+','+A.y+' '+B.x+','+B.y+' '+C.x+','+C.y+'" fill="rgba(217,119,6,.08)" stroke="#b45309" stroke-width="2" stroke-linejoin="round"/>';
|
||||
s += '<polyline points="'+rightAngleMark(B, uBA, uBC, 10)+'" fill="none" stroke="#0f172a" stroke-width="1.6"/>';
|
||||
s += '<path d="'+angleArcAuto(C, uCA, uCB, 26)+'" fill="none" stroke="#dc2626" stroke-width="2"/>';
|
||||
s += '<path d="'+angleArcAuto(A, uAB, uAC, 22)+'" fill="none" stroke="#0ea5e9" stroke-width="2"/>';
|
||||
// подписи углов
|
||||
s += '<text x="'+(C.x-30)+'" y="'+(C.y-8)+'" text-anchor="middle" font-family="Inter,sans-serif" font-size="13" font-weight="700" fill="#dc2626">30°</text>';
|
||||
s += '<text x="'+(A.x+18)+'" y="'+(A.y-8)+'" text-anchor="middle" font-family="Inter,sans-serif" font-size="13" font-weight="700" fill="#0ea5e9">60°</text>';
|
||||
// вершины и подписи
|
||||
['A','B','C'].forEach((nm,i)=>{ const P=[A,B,C][i]; s+='<circle cx="'+P.x+'" cy="'+P.y+'" r="3.5" fill="#0f172a"/>'; });
|
||||
s += '<text x="'+(A.x-10)+'" y="'+(A.y+15)+'" text-anchor="end" font-family="Inter,sans-serif" font-size="14" font-weight="700">A</text>';
|
||||
s += '<text x="'+(B.x-10)+'" y="'+(B.y-4)+'" text-anchor="end" font-family="Inter,sans-serif" font-size="14" font-weight="700">B</text>';
|
||||
s += '<text x="'+(C.x+10)+'" y="'+(C.y+15)+'" text-anchor="start" font-family="Inter,sans-serif" font-size="14" font-weight="700">C</text>';
|
||||
// длины сторон
|
||||
s += '<text x="'+(B.x-22)+'" y="'+((A.y+B.y)/2+4)+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="12" fill="#b45309">1</text>';
|
||||
s += '<text x="'+((B.x+C.x)/2)+'" y="'+(A.y+22)+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="12" fill="#b45309">√3</text>';
|
||||
const midAC={x:(A.x+C.x)/2, y:(A.y+C.y)/2};
|
||||
const nAC={x:-(C.y-A.y), y:(C.x-A.x)};
|
||||
const nL=Math.sqrt(nAC.x*nAC.x+nAC.y*nAC.y)||1;
|
||||
const labP={x: midAC.x + 16*nAC.x/nL, y: midAC.y + 16*nAC.y/nL};
|
||||
s += '<text x="'+labP.x+'" y="'+labP.y+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="12" fill="#b45309">2</text>';
|
||||
// Стандартная схема для обоих треугольников:
|
||||
// A — нижний левый угол (острый, на нём показываем основной интересующий нас угол).
|
||||
// C — нижний правый угол (прямой).
|
||||
// B — верхний правый угол (второй острый).
|
||||
// Прилежащий катет = AC (горизонтальный), противолежащий = BC (вертикальный), гипотенуза = AB.
|
||||
function drawTri(opts){
|
||||
const { Ax, Ay, b, a, angAname, angBname, sideAdjLab, sideOppLab, hypLab, title } = opts;
|
||||
const A = {x: Ax, y: Ay};
|
||||
const C = {x: Ax + b, y: Ay};
|
||||
const B = {x: C.x, y: Ay - a};
|
||||
const uCA = unitVec(C, A), uCB = unitVec(C, B);
|
||||
const uAC = unitVec(A, C), uAB = unitVec(A, B);
|
||||
const uBA = unitVec(B, A), uBC = unitVec(B, C);
|
||||
let s = '';
|
||||
// заполнение и контур треугольника
|
||||
s += '<polygon points="'+A.x+','+A.y+' '+C.x+','+C.y+' '+B.x+','+B.y+'" fill="rgba(217,119,6,.08)" stroke="#b45309" stroke-width="2" stroke-linejoin="round"/>';
|
||||
// маркер прямого угла в C
|
||||
s += '<polyline points="'+rightAngleMark(C, uCA, uCB, 11)+'" fill="none" stroke="#0f172a" stroke-width="1.6"/>';
|
||||
// дуга и подпись угла при A (основной)
|
||||
s += '<path d="'+angleArcAuto(A, uAC, uAB, 26)+'" fill="none" stroke="#dc2626" stroke-width="2"/>';
|
||||
const midA = {x:(uAC.x+uAB.x)/2, y:(uAC.y+uAB.y)/2};
|
||||
const mAlen = Math.sqrt(midA.x*midA.x+midA.y*midA.y)||1;
|
||||
s += '<text x="'+(A.x + 40*midA.x/mAlen)+'" y="'+(A.y + 40*midA.y/mAlen)+'" text-anchor="middle" dominant-baseline="middle" font-family="Inter,sans-serif" font-size="13" font-weight="800" fill="#dc2626">'+angAname+'</text>';
|
||||
// дуга и подпись угла при B
|
||||
s += '<path d="'+angleArcAuto(B, uBA, uBC, 22)+'" fill="none" stroke="#0ea5e9" stroke-width="2"/>';
|
||||
const midB = {x:(uBA.x+uBC.x)/2, y:(uBA.y+uBC.y)/2};
|
||||
const mBlen = Math.sqrt(midB.x*midB.x+midB.y*midB.y)||1;
|
||||
s += '<text x="'+(B.x + 36*midB.x/mBlen)+'" y="'+(B.y + 36*midB.y/mBlen)+'" text-anchor="middle" dominant-baseline="middle" font-family="Inter,sans-serif" font-size="13" font-weight="800" fill="#0ea5e9">'+angBname+'</text>';
|
||||
// вершины
|
||||
[A,B,C].forEach(P=>{ s+='<circle cx="'+P.x+'" cy="'+P.y+'" r="3.5" fill="#0f172a"/>'; });
|
||||
s += '<text x="'+(A.x-12)+'" y="'+(A.y+6)+'" text-anchor="end" font-family="Inter,sans-serif" font-size="14" font-weight="800">A</text>';
|
||||
s += '<text x="'+(B.x+12)+'" y="'+(B.y+4)+'" text-anchor="start" font-family="Inter,sans-serif" font-size="14" font-weight="800">B</text>';
|
||||
s += '<text x="'+(C.x+12)+'" y="'+(C.y+16)+'" text-anchor="start" font-family="Inter,sans-serif" font-size="14" font-weight="800">C</text>';
|
||||
// длина прилежащего AC
|
||||
s += '<text x="'+((A.x+C.x)/2)+'" y="'+(A.y+22)+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="13" font-weight="700" fill="#b45309">'+sideAdjLab+'</text>';
|
||||
// длина противолежащего BC
|
||||
s += '<text x="'+(C.x+8)+'" y="'+((B.y+C.y)/2+5)+'" text-anchor="start" font-family="JetBrains Mono,monospace" font-size="13" font-weight="700" fill="#b45309">'+sideOppLab+'</text>';
|
||||
// длина гипотенузы AB — над линией
|
||||
const midAB = {x:(A.x+B.x)/2, y:(A.y+B.y)/2};
|
||||
const nAB = {x:-(B.y-A.y), y:(B.x-A.x)};
|
||||
const nL = Math.sqrt(nAB.x*nAB.x+nAB.y*nAB.y)||1;
|
||||
const labP = {x: midAB.x - 18*nAB.x/nL, y: midAB.y - 18*nAB.y/nL};
|
||||
s += '<text x="'+labP.x+'" y="'+labP.y+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="13" font-weight="700" fill="#b45309">'+hypLab+'</text>';
|
||||
// заголовок
|
||||
s += '<text x="'+((A.x+C.x)/2)+'" y="22" text-anchor="middle" font-family="Unbounded,sans-serif" font-size="13" font-weight="800" fill="#92400e">30\xb0-60\xb0-90\xb0</text>';
|
||||
})();
|
||||
// Треугольник 45-45-90: оба катета 1, гипотенуза sqrt(2). Масштаб тот же.
|
||||
(function(){
|
||||
const u = 90; // покрупнее
|
||||
const Ax = 360, Ay = 180;
|
||||
const A = {x: Ax, y: Ay};
|
||||
const B = {x: Ax, y: Ay - u};
|
||||
const C = {x: Ax + u, y: Ay};
|
||||
const uBA = unitVec(B, A);
|
||||
const uBC = unitVec(B, C);
|
||||
const uCA = unitVec(C, A);
|
||||
const uCB = unitVec(C, B);
|
||||
const uAB = unitVec(A, B);
|
||||
const uAC = unitVec(A, C);
|
||||
s += '<polygon points="'+A.x+','+A.y+' '+B.x+','+B.y+' '+C.x+','+C.y+'" fill="rgba(217,119,6,.08)" stroke="#b45309" stroke-width="2" stroke-linejoin="round"/>';
|
||||
s += '<polyline points="'+rightAngleMark(B, uBA, uBC, 10)+'" fill="none" stroke="#0f172a" stroke-width="1.6"/>';
|
||||
s += '<path d="'+angleArcAuto(C, uCA, uCB, 28)+'" fill="none" stroke="#dc2626" stroke-width="2"/>';
|
||||
s += '<path d="'+angleArcAuto(A, uAB, uAC, 26)+'" fill="none" stroke="#0ea5e9" stroke-width="2"/>';
|
||||
s += '<text x="'+(C.x-30)+'" y="'+(C.y-8)+'" text-anchor="middle" font-family="Inter,sans-serif" font-size="13" font-weight="700" fill="#dc2626">45°</text>';
|
||||
s += '<text x="'+(A.x+22)+'" y="'+(A.y-8)+'" text-anchor="middle" font-family="Inter,sans-serif" font-size="13" font-weight="700" fill="#0ea5e9">45°</text>';
|
||||
['A','B','C'].forEach((nm,i)=>{ const P=[A,B,C][i]; s+='<circle cx="'+P.x+'" cy="'+P.y+'" r="3.5" fill="#0f172a"/>'; });
|
||||
s += '<text x="'+(A.x-10)+'" y="'+(A.y+15)+'" text-anchor="end" font-family="Inter,sans-serif" font-size="14" font-weight="700">A</text>';
|
||||
s += '<text x="'+(B.x-10)+'" y="'+(B.y-4)+'" text-anchor="end" font-family="Inter,sans-serif" font-size="14" font-weight="700">B</text>';
|
||||
s += '<text x="'+(C.x+10)+'" y="'+(C.y+15)+'" text-anchor="start" font-family="Inter,sans-serif" font-size="14" font-weight="700">C</text>';
|
||||
s += '<text x="'+(B.x-22)+'" y="'+((A.y+B.y)/2+4)+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="12" fill="#b45309">1</text>';
|
||||
s += '<text x="'+((B.x+C.x)/2)+'" y="'+(A.y+22)+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="12" fill="#b45309">1</text>';
|
||||
const midAC={x:(A.x+C.x)/2, y:(A.y+C.y)/2};
|
||||
const nAC={x:-(C.y-A.y), y:(C.x-A.x)};
|
||||
const nL=Math.sqrt(nAC.x*nAC.x+nAC.y*nAC.y)||1;
|
||||
const labP={x: midAC.x + 16*nAC.x/nL, y: midAC.y + 16*nAC.y/nL};
|
||||
s += '<text x="'+labP.x+'" y="'+labP.y+'" text-anchor="middle" font-family="JetBrains Mono,monospace" font-size="12" fill="#b45309">√2</text>';
|
||||
s += '<text x="'+((A.x+C.x)/2)+'" y="22" text-anchor="middle" font-family="Unbounded,sans-serif" font-size="13" font-weight="800" fill="#92400e">45\xb0-45\xb0-90\xb0</text>';
|
||||
})();
|
||||
s += '<text x="'+((A.x+C.x)/2)+'" y="22" text-anchor="middle" font-family="Unbounded,sans-serif" font-size="13" font-weight="800" fill="#92400e">'+title+'</text>';
|
||||
return s;
|
||||
}
|
||||
let s = '';
|
||||
// 30-60-90 (слева): катет AC = √3 (прилежащий 30°), катет BC = 1 (противолежащий 30°), гипотенуза AB = 2.
|
||||
// Острый угол A = 30°, острый B = 60°.
|
||||
s += drawTri({
|
||||
Ax: 30, Ay: 180,
|
||||
b: Math.sqrt(3)*70, // прилежащий к 30° (длинный)
|
||||
a: 70, // противолежащий 30° (короткий)
|
||||
angAname: '30°', angBname: '60°',
|
||||
sideAdjLab: '√3', sideOppLab: '1', hypLab: '2',
|
||||
title: '30°–60°–90°'
|
||||
});
|
||||
// 45-45-90 (справа): оба катета = 1, гипотенуза = √2.
|
||||
s += drawTri({
|
||||
Ax: 380, Ay: 180,
|
||||
b: 95,
|
||||
a: 95,
|
||||
angAname: '45°', angBname: '45°',
|
||||
sideAdjLab: '1', sideOppLab: '1', hypLab: '√2',
|
||||
title: '45°–45°–90°'
|
||||
});
|
||||
svg.innerHTML = s;
|
||||
addXp(10,'p3-iv1'); bumpProgress('p3', 15);
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user