Linien: modulares Segment-System (Strich/Punkt/Luecke) + Loop-Vorschau
Der Linien-Editor ist modular: eine Linie ist eine geordnete, loopende Folge aus Segmenten Strich (Laenge), Punkt (Dot) und Luecke (Laenge) — beliebige Sequenzen (Volllinie/Strichlinie/Punktlinie/Strich-Punkt als Presets, plus frei), die Schluss-Luecke ist die letzte Luecke. Datenbasis bleibt LineStyle.dash (mm, alternierend); ein Punkt ist ein 0-Laengen-AN-Segment. Enthaelt dash eine 0, wird die Linie mit runder Kappe gezeichnet, damit Punkte als Dots erscheinen (Live + Print; GL/DXF Folgearbeit). Neue reine Segment-Logik in ui/lineSegments.ts. LineSwatch zeigt den ersten Loop dunkel und 2 weitere grau (Loop-Kontext). 14 neue Tests, 127 gruen.
This commit is contained in:
+42
-3
@@ -10,6 +10,7 @@
|
||||
|
||||
import { useId } from "react";
|
||||
import type { HatchStyle, LineStyle } from "../model/types";
|
||||
import { dashHasDot } from "./lineSegments";
|
||||
|
||||
// ── Kleiner deterministischer PRNG (mulberry32) ────────────────────────────
|
||||
// Für „random"-Striche: stabil pro Seed, damit die Vorschau bei gleichem
|
||||
@@ -330,8 +331,8 @@ export function LineSwatch({
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
const dasharray = style.dash ? style.dash.map((d) => d * 4).join(" ") : undefined;
|
||||
} else if (!style.dash || !style.dash.length) {
|
||||
// Volllinie: durchgezogen, eine dunkle Linie.
|
||||
path = (
|
||||
<line
|
||||
x1={x0}
|
||||
@@ -340,10 +341,48 @@ export function LineSwatch({
|
||||
y2={midY}
|
||||
stroke="currentColor"
|
||||
strokeWidth={px}
|
||||
strokeDasharray={dasharray}
|
||||
strokeLinecap="butt"
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
// Muster-Linie (Strich/Punkt/Lücke, loopend): den ERSTEN Loop in Ink-Farbe
|
||||
// (currentColor), danach 2 weitere Loops in Grau (var(--muted)) — so sieht man
|
||||
// den fortgesetzten Loop. Punkte (0-Längen-Segmente) brauchen runde Kappen.
|
||||
const PX_PER_MM = 4;
|
||||
const dpx = style.dash.map((d) => d * PX_PER_MM);
|
||||
const dasharray = dpx.join(" ");
|
||||
const loopLen = dpx.reduce((a, b) => a + b, 0) || PX_PER_MM;
|
||||
const cap = dashHasDot(style.dash) ? "round" : "butt";
|
||||
// Der graue Teil beginnt exakt an der Loop-Grenze (x0 + loopLen) → das Muster
|
||||
// läuft phasengleich weiter (dash startet bei jedem Pfadanfang neu).
|
||||
const darkEnd = Math.min(x1, x0 + loopLen);
|
||||
const greyEnd = Math.min(x1, x0 + loopLen * 3);
|
||||
path = (
|
||||
<>
|
||||
{greyEnd > darkEnd && (
|
||||
<line
|
||||
x1={darkEnd}
|
||||
y1={midY}
|
||||
x2={greyEnd}
|
||||
y2={midY}
|
||||
stroke="var(--muted)"
|
||||
strokeWidth={px}
|
||||
strokeDasharray={dasharray}
|
||||
strokeLinecap={cap}
|
||||
/>
|
||||
)}
|
||||
<line
|
||||
x1={x0}
|
||||
y1={midY}
|
||||
x2={darkEnd}
|
||||
y2={midY}
|
||||
stroke="currentColor"
|
||||
strokeWidth={px}
|
||||
strokeDasharray={dasharray}
|
||||
strokeLinecap={cap}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user