fix: vertikale Sammelleiste erreicht den Eltern-Stub wieder (D65)
Zwei Geometrie-Fehler bei Gruppen mit wenigen Kindern: :only-child schaltete die Leiste ab, obwohl Stub (50 %) und Abzweig (23 px) seit dem 20-px- Zusatzabstand nicht mehr zusammenfallen (6,6–15,8 px Lücke); und bei einem großen Teilbaum im letzten Kind endete die Leiste über dem Stub (bis 98 px). Fix: CSS-Verbinder 23px→50 % am Einzelkind, alignVRails() + --vrail-ext für das letzte Kind. Export und Kompakt-Modus waren nie betroffen. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
94aa16efbd
commit
07e4116bd9
@@ -474,6 +474,18 @@ verworfene Elemente. Quelle sind ES-Module unter `src/`; `index.html` ist der
|
||||
müssen **hinter** den first/last-Regeln stehen: Ein einziges Kind ist auch
|
||||
das letzte, und bei gleicher Spezifität gewinnt die spätere Regel — genau
|
||||
daran war `:only-child::after` jahrelang wirkungslos.
|
||||
- `--vrail-ext` (D65): Im **vertikalen** Modus dockt der Eltern-Stub bei 50 %
|
||||
der Gruppenhöhe an, die Sammelleiste endet aber am 23-px-Abzweig des letzten
|
||||
Kindes — trägt das einen großen Teilbaum, liegt die Gruppenmitte darunter
|
||||
und der Stub hinge in der Luft. `alignVRails()` (läuft an denselben drei
|
||||
Stellen wie `alignStems()`) misst das und verlängert die Leiste per
|
||||
`--vrail-ext`; das **einzige** Kind löst CSS allein
|
||||
(`:only-child::after{top:23px;height:calc(50% - 23px)}` — dort ist
|
||||
Gruppenhöhe == Kindhöhe). Kein `border:0` mehr am nicht-has-and-Einzelkind:
|
||||
Genau das war die Lücke („kurze vertikale Linien fehlen"). has-and-Kinder
|
||||
brauchen beides nie (Abzweig bei 50 % der Zelle). Wer an den
|
||||
vertikalen first/last/only-Regeln dreht, prüft mit dem Geometrie-Scanner
|
||||
(Pseudo-Element-Rects: Leisten-Segmente vs. Stub-Höhe) statt mit dem Auge.
|
||||
- Kleiner Bildschirm: `body.mobile` (per `matchMedia`, ≤ 640 px) zeigt **genau
|
||||
einen** Bereich — `body.pane-diagram` bzw. `body.pane-text`, umgeschaltet über
|
||||
je einen festen Knopf pro Titelzeile (`#paneToText`/`#paneToDiagram`,
|
||||
|
||||
+29
-1
@@ -206,6 +206,7 @@ function render(){
|
||||
renderLineNos();
|
||||
applyOptStairs(); /* muss vor dem Messen laufen — es verschiebt Knoten */
|
||||
alignStems();
|
||||
alignVRails();
|
||||
drawCheapPath();
|
||||
/* Querverbindungen (D41) zeichnet highlightCurrentNode() unten mit —
|
||||
es kennt die zweite Hälfte der Auswahl (Cursor-Zeile). */
|
||||
@@ -332,6 +333,32 @@ function alignStems(){
|
||||
});
|
||||
}
|
||||
|
||||
/* Sammelleisten-Verlängerung im vertikalen Modus (D65). Der Eltern-Stub dockt
|
||||
bei 50 % der Gruppenhöhe an, die Leiste endet aber am 23-px-Abzweig des
|
||||
letzten Kindes — trägt das einen großen Teilbaum, liegt die Gruppenmitte
|
||||
TIEFER und der Stub hinge in der Luft (gemessen: 4,5 bis 98 px Lücke). CSS
|
||||
kann die Gruppenmitte relativ zum letzten <li> nicht ausdrücken; wie bei
|
||||
`alignStems()` misst deshalb JS und setzt `--vrail-ext` (unskalierte px,
|
||||
durch effZoom() zurückgerechnet). Nur nicht-has-and-Letztkinder: Bei
|
||||
has-and liegt der Abzweig bei 50 % der Zelle, und die Gruppenmitte liegt
|
||||
beweisbar nie darunter. Nach oben kann die Mitte nie aus der Leiste fallen
|
||||
(der erste Abzweig liegt höchstens 23 px unter dem Gruppenanfang). */
|
||||
function alignVRails(){
|
||||
out.querySelectorAll('ul.and>li').forEach(li => li.style.removeProperty('--vrail-ext'));
|
||||
if(!out.classList.contains('vertical')) return;
|
||||
const z = effZoom() || 1;
|
||||
out.querySelectorAll('li.has-and>ul.and').forEach(ul => {
|
||||
const kids = [...ul.children].filter(e => e.tagName === 'LI');
|
||||
if(kids.length < 2) return; /* :only-child löst CSS allein (50 %) */
|
||||
const last = kids[kids.length - 1];
|
||||
if(last.classList.contains('has-and')) return;
|
||||
const ur = ul.getBoundingClientRect(), lr = last.getBoundingClientRect();
|
||||
if(!ur.height) return; /* Panel eingeklappt */
|
||||
const ext = (ur.top + ur.height/2 - lr.top)/z;
|
||||
if(ext > 23.5) last.style.setProperty('--vrail-ext', ext.toFixed(1) + 'px');
|
||||
});
|
||||
}
|
||||
|
||||
function drawCheapPath(){
|
||||
out.querySelectorAll('svg.cheap-overlay').forEach(e => e.remove());
|
||||
if(!cheapPathOn) return;
|
||||
@@ -1752,6 +1779,7 @@ function applyLayout(mode){
|
||||
if(!isMobile()) applySplit(); /* Desktop: Preset neu setzen. Mobil: freie --drow-Aufteilung behalten */
|
||||
applyOptStairs(); /* Treppe gilt nur im Fächer — beim Moduswechsel bauen/auflösen */
|
||||
alignStems(); /* Stiel gilt nur im Fächer — beim Moduswechsel neu setzen/löschen */
|
||||
alignVRails(); /* Leisten-Verlängerung gilt nur vertikal — ebenso (D65) */
|
||||
drawCheapPath(); /* Blatt-Positionen ändern sich mit dem Modus */
|
||||
drawDepLinks(); /* Knoten-Positionen ebenso (D41) */
|
||||
}
|
||||
@@ -1805,7 +1833,7 @@ function setMobilePane(pane, save){
|
||||
Live-Geometrie zeichnet, muss deshalb nach dem Sichtbarwerden neu laufen —
|
||||
im Diagramm dieselben vier Schritte wie beim Moduswechsel (applyLayout),
|
||||
im Editor der Zeilennummern-Streifen, der am Spiegel misst (D33). */
|
||||
if(pane === 'diagram'){ applyOptStairs(); alignStems(); drawCheapPath(); drawDepLinks(); }
|
||||
if(pane === 'diagram'){ applyOptStairs(); alignStems(); alignVRails(); drawCheapPath(); drawDepLinks(); }
|
||||
else renderLineNos();
|
||||
if(save) saveUI();
|
||||
}
|
||||
|
||||
+13
-1
@@ -1317,7 +1317,19 @@
|
||||
Linien zu zentrierten Zwischenknoten ins Leere. Die Enden der Sammelleiste
|
||||
folgen demselben Abzweigpunkt des jeweiligen Rand-Kindes. */
|
||||
.tree.vertical li.has-and>ul.and>li:first-child::after{top:23px;height:calc(100% - 23px)}
|
||||
.tree.vertical li.has-and>ul.and>li:only-child::after{border:0}
|
||||
/* Einziges Kind: KEIN border:0 mehr (D65). Der Eltern-Stub dockt bei 50 % der
|
||||
Gruppenhöhe an, der Kind-Abzweig liegt fest bei 23 px — seit dem
|
||||
20-px-Zusatzabstand unten (und erst recht bei mehrzeiligen Knoten, D64)
|
||||
fallen die beiden NICHT mehr zusammen. Das Verbindungsstück ist hier rein
|
||||
in CSS ausdrückbar, weil Gruppenhöhe == Kindhöhe (ul hat padding-top:0). */
|
||||
.tree.vertical li.has-and>ul.and>li:only-child::after{top:23px;height:max(0px, calc(50% - 23px))}
|
||||
/* Letztes Kind mit großem Teilbaum (D65): Die Leiste endet am 23-px-Abzweig,
|
||||
der Eltern-Stub dockt aber bei 50 % der GRUPPE an — liegt der tiefer
|
||||
(großer Teilbaum im letzten Kind), hinge er in der Luft. `alignVRails()`
|
||||
in app.js misst das und verlängert die Leiste per --vrail-ext bis zum
|
||||
Stub. has-and-Kinder brauchen das nie (Abzweig bei 50 % der Zelle, und
|
||||
50 % der Gruppe liegt beweisbar darüber). */
|
||||
.tree.vertical li.has-and>ul.and>li:last-child:not(.has-and):not(:only-child)::after{height:var(--vrail-ext, 23px)}
|
||||
.tree.vertical li.has-and>ul.and>li.has-and::before{top:50%}
|
||||
.tree.vertical li.has-and>ul.and>li.has-and:first-child::after{top:50%;height:50%}
|
||||
.tree.vertical li.has-and>ul.and>li.has-and:last-child::after{top:0;height:50%}
|
||||
|
||||
Reference in New Issue
Block a user