fix: Abhängigkeits-Pfeilspitzen offen und grau — kein gefülltes Dreieck (D41-Nachtrag)

Das gefüllte Dreieck stach als einziger satter Fleck aus der gepunkteten
grauen Linie heraus. Jetzt ein offener Winkel aus zwei dünnen Strichen
im selben Grau und Gewicht wie die Linie; die Fokus-Hervorhebung bekommt
denselben Winkel in Tinte. Export identisch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-08-22 19:37:58 +02:00
co-authored by Claude Fable 5
parent c6f42f8da1
commit a8c5e54f11
5 changed files with 17 additions and 7 deletions
+5
View File
@@ -2009,6 +2009,11 @@ gekrümmten Ebene und begegnen den Rahmenkanten nie. Die **Hervorhebung**
(fokussierter Knoten) bleibt durchgezogen in Tinte: Sie ist ausdrücklich
angefordert und soll sich nach vorn drängen. Export identisch nachgezogen.
Zweiter Schritt derselben Rückmeldung: Auch die **Pfeilspitze** ist jetzt
**offen** (ein Winkel aus zwei dünnen grauen Strichen) statt eines gefüllten
Dreiecks — das Dreieck stach als einziger satter Fleck aus der gepunkteten
Linie heraus. Die Hervorhebung bekommt denselben Winkel in Tinte.
## D42 — Closure-Pfad: erschöpfend über die gekoppelten Gruppen, gierig nur benannt
Die letzte Baustelle aus D34: Mit Abhängigkeiten zählt der günstigste Pfad
nicht mehr den gewählten Teilbaum, sondern die **Hülle** — jeder nötige Knoten
+3 -3
View File
@@ -643,9 +643,9 @@ Abhängigkeiten werden als **optisch sekundäre** Kanten gezeichnet: dünn,
blassgrau (`#6B7A8C`), **gepunktet** und **geschwungen** — Punktierung und
Krümmung unterscheiden sie doppelt von den Baumlinien (durchgezogen bzw.
gestrichelt, immer orthogonal) und halten sie zurückhaltend — auf einer
eigenen Zeichenebene **hinter** den Knoten, mit einer kleinen **Pfeilspitze
auf das Gebrauchte** („braucht“-Richtung). Der Baum trägt weiterhin die
Hauptaussage.
eigenen Zeichenebene **hinter** den Knoten, mit einer kleinen **offenen
Pfeilspitze auf das Gebrauchte** („braucht“-Richtung; ein Winkel aus zwei
Strichen, kein gefülltes Dreieck). Der Baum trägt weiterhin die Hauptaussage.
- Die Kanten des **ausgewählten** Knotens — Tastaturfokus im Diagramm, sonst
der Knoten der Cursor-Zeile — liegen hervorgehoben in Tinte auf einer
+4 -2
View File
@@ -336,13 +336,15 @@ function depCurve(a, b){
return {d:`M${p1.x.toFixed(1)},${p1.y.toFixed(1)} Q${ctrl.x.toFixed(1)},${ctrl.y.toFixed(1)} ${p2.x.toFixed(1)},${p2.y.toFixed(1)}`,
end:p2, ctrl};
}
/* Offene Pfeilspitze (Winkel aus zwei Strichen, D41-Nachtrag): ein gefülltes
Dreieck stach als einziger satter Fleck aus der gepunkteten Linie heraus. */
function depArrow(end, from){
const dx = end.x - from.x, dy = end.y - from.y;
const l = Math.hypot(dx, dy) || 1;
const ux = dx/l, uy = dy/l, s = 5;
const a = {x: end.x - ux*s*1.8 - uy*s, y: end.y - uy*s*1.8 + ux*s};
const b = {x: end.x - ux*s*1.8 + uy*s, y: end.y - uy*s*1.8 - ux*s};
return `M${end.x.toFixed(1)},${end.y.toFixed(1)} L${a.x.toFixed(1)},${a.y.toFixed(1)} L${b.x.toFixed(1)},${b.y.toFixed(1)} Z`;
return `M${a.x.toFixed(1)},${a.y.toFixed(1)} L${end.x.toFixed(1)},${end.y.toFixed(1)} L${b.x.toFixed(1)},${b.y.toFixed(1)}`;
}
/* „Ausgewählt" heißt: Tastaturfokus im Diagramm, sonst der Knoten der
Cursor-Zeile (D25) — beide Lesarten von „ich schaue auf diesen Knoten". */
@@ -495,7 +497,7 @@ function diagramToSvg(){
depEdges().forEach(([from, to]) => {
const c = depCurve(R(from), R(to));
parts.push(`<path d="${c.d}" fill="none" stroke="#6B7A8C" stroke-width="1.5" opacity="0.4" stroke-linecap="round" stroke-dasharray="0.1 5"/>`);
parts.push(`<path d="${depArrow(c.end, c.ctrl)}" fill="#6B7A8C" opacity="0.4"/>`);
parts.push(`<path d="${depArrow(c.end, c.ctrl)}" fill="none" stroke="#6B7A8C" stroke-width="1.5" opacity="0.4" stroke-linecap="round" stroke-linejoin="round"/>`);
});
/* 1b) Günstigster-Pfad: kräftige Linie hinter den Knoten */
+4 -2
View File
@@ -710,9 +710,11 @@
.dep-overlay{position:absolute;left:0;top:0;overflow:visible;pointer-events:none}
.dep-edge{fill:none;stroke:var(--muted);stroke-width:1.5;opacity:.4;
stroke-linecap:round;stroke-dasharray:.1 5}
.dep-arrow{fill:var(--muted);opacity:.4}
/* Offene Pfeilspitze — grau und dünn wie die Linie, kein gefülltes Dreieck. */
.dep-arrow{fill:none;stroke:var(--muted);stroke-width:1.5;opacity:.4;
stroke-linecap:round;stroke-linejoin:round}
.dep-edge.hl{stroke:var(--line);stroke-width:2;opacity:.9;stroke-dasharray:none}
.dep-arrow.hl{fill:var(--line);opacity:.9}
.dep-arrow.hl{stroke:var(--line);stroke-width:2;opacity:.9}
.cheap-path{fill:none;stroke:var(--or);stroke-width:2.5;stroke-linecap:round;
stroke-dasharray:8 6;opacity:.9}
.cheap-path.faint{opacity:.2}
@@ -0,0 +1 @@
{"version":"4.1.11","results":[[":frontend/tests/render.test.js",{"duration":98.47688799999997,"failed":false}],[":frontend/tests/focusmark.test.js",{"duration":35.79027499999995,"failed":false}],[":frontend/tests/fold.test.js",{"duration":41.154863999999975,"failed":false}],[":frontend/tests/optional.test.js",{"duration":35.42018200000001,"failed":false}],[":frontend/tests/parser.test.js",{"duration":33.422897999999975,"failed":false}],[":frontend/tests/xor.test.js",{"duration":52.44134100000002,"failed":false}],[":frontend/tests/desc.test.js",{"duration":31.248038000000008,"failed":false}],[":frontend/tests/deps.test.js",{"duration":31.736107000000004,"failed":false}],[":frontend/tests/closure.test.js",{"duration":24.077101999999968,"failed":false}],[":frontend/tests/effective.test.js",{"duration":27.93907200000001,"failed":false}],[":frontend/tests/ids.test.js",{"duration":25.51923499999998,"failed":false}],[":frontend/tests/remote.test.js",{"duration":20.999619999999993,"failed":false}],[":frontend/tests/warnings.test.js",{"duration":9.594386999999983,"failed":false}],[":frontend/tests/fresh.test.js",{"duration":22.15039999999999,"failed":false}]]}