diff --git a/frontend/textbooks/algebra_8.html b/frontend/textbooks/algebra_8.html index 0606b55..fe2eafb 100644 --- a/frontend/textbooks/algebra_8.html +++ b/frontend/textbooks/algebra_8.html @@ -2238,7 +2238,7 @@ function buildP2(){ `)} ${widget('Числовая прямая с корнями', 'VISUAL', 'Нажимайте кнопки, чтобы поставить точки √n и π на прямую. Точные десятичные значения — в подсказках.', ` -
+
@@ -2442,25 +2442,54 @@ function initNumLine(){ function nlRender(){ const line = document.getElementById('nl-line'); line.innerHTML = ''; - const w = line.clientWidth; - // axis 0..15 - const axis = el('div', {style:'position:absolute;top:60px;left:3%;right:3%;height:2px;background:var(--text)'}); + // axis 0..15 — нижняя часть, чтобы сверху было место под подписи в несколько уровней + const AXIS_Y = 100; + const axis = el('div', {style:`position:absolute;top:${AXIS_Y}px;left:3%;right:3%;height:2px;background:var(--text)`}); line.appendChild(axis); // ticks 0..15 const lo = 0, hi = 15; for(let i = lo; i <= hi; i++){ const x = 3 + (i - lo) / (hi - lo) * 94; - const t = el('div', {style:`position:absolute;top:54px;left:${x}%;width:2px;height:14px;background:var(--text);transform:translateX(-50%)`}); + const t = el('div', {style:`position:absolute;top:${AXIS_Y-6}px;left:${x}%;width:2px;height:14px;background:var(--text);transform:translateX(-50%)`}); line.appendChild(t); - const lab = el('div', {style:`position:absolute;top:72px;left:${x}%;transform:translateX(-50%);font-size:.74rem;font-family:'JetBrains Mono',monospace;color:var(--muted)`}, ''+i); + const lab = el('div', {style:`position:absolute;top:${AXIS_Y+12}px;left:${x}%;transform:translateX(-50%);font-size:.74rem;font-family:'JetBrains Mono',monospace;color:var(--muted)`}, ''+i); line.appendChild(lab); } - NL_POINTS.forEach((p,i)=>{ - const x = 3 + (p.v - lo) / (hi - lo) * 94; - const pt = el('div', {style:`position:absolute;top:54px;left:${x}%;width:14px;height:14px;background:var(--pri);border-radius:50%;transform:translateX(-50%);border:2.5px solid var(--card);box-shadow:0 0 0 2px var(--pri);cursor:pointer;z-index:2`}); + // Сортируем по x для расчёта уровней без перекрытия + const w = line.clientWidth || 600; + const labelHalfPxApprox = 22; // полу-ширина подписи в пикселях + const placed = []; // {xPct, level} + const sorted = NL_POINTS.map((p,i)=>({...p, _i:i})).sort((a,b)=>a.v-b.v); + sorted.forEach(p=>{ + const xPct = 3 + (p.v - lo) / (hi - lo) * 94; + // Найти минимальный уровень без перекрытия с placed + let level = 0; + while(true){ + const conflict = placed.some(q=>{ + if(q.level !== level) return false; + const dxPx = Math.abs(q.xPct - xPct) / 100 * w; + return dxPx < (labelHalfPxApprox * 2 + 4); + }); + if(!conflict) break; + level++; + if(level > 8) break; + } + placed.push({xPct, level}); + p._level = level; + }); + sorted.forEach(p=>{ + const xPct = 3 + (p.v - lo) / (hi - lo) * 94; + const pt = el('div', {style:`position:absolute;top:${AXIS_Y-6}px;left:${xPct}%;width:14px;height:14px;background:var(--pri);border-radius:50%;transform:translateX(-50%);border:2.5px solid var(--card);box-shadow:0 0 0 2px var(--pri);cursor:pointer;z-index:2`}); pt.title = p.lab + ' ≈ ' + p.v.toFixed(4); line.appendChild(pt); - const lab = el('div', {style:`position:absolute;top:${20 + (i%3)*12}px;left:${x}%;transform:translateX(-50%);font-size:.78rem;font-weight:700;color:var(--pri);background:var(--card);padding:2px 6px;border-radius:5px;border:1px solid var(--pri);font-family:'JetBrains Mono',monospace`}, p.lab); + // Подпись сверху, нескольких уровней; линия-выноска вниз к точке + const labY = 4 + p._level * 20; + const stemTop = labY + 18; + const stemHeight = AXIS_Y - stemTop - 2; + if(stemHeight > 0){ + line.appendChild(el('div', {style:`position:absolute;top:${stemTop}px;left:${xPct}%;width:1px;height:${stemHeight}px;background:var(--pri);opacity:.45;transform:translateX(-50%);z-index:1`})); + } + const lab = el('div', {style:`position:absolute;top:${labY}px;left:${xPct}%;transform:translateX(-50%);font-size:.78rem;font-weight:700;color:var(--pri);background:var(--card);padding:2px 7px;border-radius:5px;border:1px solid var(--pri);font-family:'JetBrains Mono',monospace;white-space:nowrap;z-index:3;box-shadow:0 1px 4px rgba(0,0,0,.08)`}, p.lab); line.appendChild(lab); }); }