Post 2: Slide 2 wird ein Knaeuel

Statt drei Kaesten an einer Schiene jetzt fuenf beschriftete Kanaele mit
einer gestrichelten Leitung dazwischen. Vorbild war ein fremder Beitrag,
uebersetzt in unsere Handschrift und ohne fremde Produktnamen: E-Mails,
Zettel im Auto, Tabellen, Fotos auf dem Handy, Ordner im Regal. Das ist
naeher am SHK-Betrieb als WhatsApp und Excel.

Bewusst ohne Aufloesung. Das Vorbild packt Problem und Antwort in ein
Motiv, bei uns ist die Antwort Slide 5. Zweimal dieselbe Pointe waere
einmal zu viel.

Die Anbindung der Leitung war im ersten Anlauf falsch, und zwar aus zwei
Gruenden. Die Stuetzpunkte lagen direkt auf der Kastenkante, danach lief
die Bahn irgendwohin: die Linie streifte den Kasten, statt an ihm
anzusetzen. Und wo zwei Stuetzpunkte fast aufeinanderlagen, warf die
weiche Kurve einen Zipfel. Jetzt bekommt jedes Stueck vor und hinter dem
Kasten einen Punkt auf gleicher Hoehe, 52 px daneben. Die Bahn laeuft
dadurch waagerecht heraus und waagerecht hinein und haengt sichtbar am
Kasten.

Die Leitung traegt den Akzent in Gelb. Damit steht ein Gegensatz, der
auch fuer die naechsten Beitraege taugt: gestrichelt und gelb heisst
gewachsen, durchgezogen und gelb heisst verbunden. Dieselbe Farbe, die
Strichart trennt die Aussage.

Die Kaesten sind chamfert, also die Markenform, nicht die runden Chips
des Vorbilds. Neu als Primitiv dazu: chamfer als gezeichneter Achtkant.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
dejanandClaude Opus 5 committed 2026-08-12 00:14:20 +02:00
1 parent 45342df1bd
commit 6f58896f12
1 file changed
+172 -10
+172 -10
View File
@@ -1337,6 +1337,21 @@
].join("");
}
/* Der Chamfer als gezeichneter Kasten: acht Kanten statt vier. Das ist die
Markenform aus rules.md Paragraf 3, hier von Hand gezogen. */
function chamfer(x, y, w, h, c, o) {
o = o || {};
const ue = o.ue == null ? 2.5 : o.ue;
const p = [[x + c, y], [x + w - c, y], [x + w, y + c], [x + w, y + h - c],
[x + w - c, y + h], [x + c, y + h], [x, y + h - c], [x, y + c]];
let d = "";
for (let i = 0; i < 8; i++) {
const a = p[i], b = p[(i + 1) % 8];
d += strich(a[0], a[1], b[0], b[1], { ue: i % 2 ? 1 : ue });
}
return d;
}
/* Schraffur als Schattierung: parallele Striche, an den Enden kuerzer, damit
das Feld nicht als Block steht. */
function schraff(x, y, w, h, abstand, neig) {
@@ -1370,7 +1385,8 @@
o = o || {};
return '<path d="' + d + '" fill="none" stroke="' + (o.f || TINTE) +
'" stroke-width="' + (o.w || 3.1) + '" stroke-linecap="round" stroke-linejoin="round"' +
(o.op ? ' stroke-opacity="' + o.op + '"' : '') + '/>';
(o.op ? ' stroke-opacity="' + o.op + '"' : '') +
(o.strichel ? ' stroke-dasharray="' + o.strichel + '"' : '') + '/>';
};
const schatten = d => zug(d, { w: 1.9, op: .34 });
@@ -1564,6 +1580,160 @@
}
/* ─── Aufbau ───────────────────────────────────────────────────────────── */
/* ─── Slide 2: nur so gewachsen ──────────────────────────────────────────
Ein Knaeuel aus Kanaelen, durch das sich eine gestrichelte Leitung windet.
Bewusst ohne Aufloesung: das Gegenbild dazu ist Slide 5, und die Pointe
soll nicht zweimal vorkommen.
Die Namen sind allgemein gehalten, keine fremden Produkte. */
function glyBrief(cx, cy) {
const w = 30, h = 21, x = cx - w / 2, y = cy - h / 2;
return rechteck(x, y, w, h, { ue: 1.6 }) +
glatt([[x + 2, y + 3], [cx, y + h * 0.68], [x + w - 2, y + 3]], false);
}
function glyZettel(cx, cy) {
const w = 26, h = 32, x = cx - w / 2, y = cy - h / 2, e = 11;
return glatt([[x, y], [x + w - e, y], [x + w, y + e], [x + w, y + h],
[x, y + h], [x, y]], false) +
glatt([[x + w - e, y], [x + w - e, y + e], [x + w, y + e]], false);
}
function glyTabelle(cx, cy) {
const w = 30, h = 24, x = cx - w / 2, y = cy - h / 2;
let d = rechteck(x, y, w, h, { ue: 1.6 });
d += strich(x, y + h / 3, x + w, y + h / 3, { j: .7, b: .6 });
d += strich(x, y + h * 2 / 3, x + w, y + h * 2 / 3, { j: .7, b: .6 });
d += strich(x + w / 3, y, x + w / 3, y + h, { j: .7, b: .6 });
return d;
}
function glyHandy(cx, cy) {
const w = 20, h = 32, x = cx - w / 2, y = cy - h / 2;
return rechteck(x, y, w, h, { ue: 1.4 }) +
strich(x + 6, y + 4, x + w - 6, y + 4, { j: .6, b: .5 }) +
kringel(cx, y + h - 5, 1.9);
}
function glyOrdner(cx, cy) {
const w = 30, h = 26, x = cx - w / 2, y = cy - h / 2;
return rechteck(x, y + 6, w, h - 6, { ue: 1.4 }) +
glatt([[x + 1, y + 6], [x + 3, y], [x + 13, y], [x + 15, y + 6]], false);
}
/* Die kleinen Kacheln, die im Vorbild lose dazwischen schweben. */
function kachel(cx, cy, art, gr) {
const s = gr || 52, x = cx - s / 2, y = cy - s / 2;
let d = rechteck(x, y, s, s, { ue: 2.5 });
const f = s / 52;
if (art === "blatt") {
d += rechteck(x + 16 * f, y + 13 * f, 20 * f, 26 * f, { ue: 1.4 });
[20, 26, 32].forEach(o => {
d += strich(x + 20 * f, y + o * f, x + 32 * f, y + o * f, { j: .6, b: .5 });
});
} else if (art === "bild") {
d += rechteck(x + 13 * f, y + 15 * f, 26 * f, 22 * f, { ue: 1.4 });
d += glatt([[x + 16 * f, y + 33 * f], [x + 23 * f, y + 23 * f], [x + 29 * f, y + 30 * f],
[x + 32 * f, y + 26 * f], [x + 36 * f, y + 33 * f]], false);
} else {
d += kringel(cx, y + 19 * f, 6 * f);
d += glatt([[x + 14 * f, y + 40 * f], [x + 15 * f, y + 32 * f], [cx, y + 28 * f],
[x + s - 15 * f, y + 32 * f], [x + s - 14 * f, y + 40 * f]], false);
}
return d;
}
/* Eine ausholende Schlaufe zwischen zwei Ankern. Sie bauscht immer von der
Kachelspalte weg, damit die Leitung keine Beschriftung kreuzt: auf einem
durchscheinenden Grund kann kein Kasten sie verdecken. */
function schlaufe(ax, ay, bx, by, weite, seite) {
const dx = bx - ax, dy = by - ay, l = Math.hypot(dx, dy) || 1;
const nx = (dy / l) * seite, ny = (-dx / l) * seite;
return [
[ax, ay],
[ax + nx * weite * 0.62 + dx * 0.06, ay + ny * weite * 0.62 + dy * 0.06],
[(ax + bx) / 2 + nx * weite, (ay + by) / 2 + ny * weite],
[bx + nx * weite * 0.62 - dx * 0.06, by + ny * weite * 0.62 - dy * 0.06],
[bx, by],
];
}
/* Ein Stueck Leitung von Kasten zu Kasten.
Der erste Versuch legte die Stuetzpunkte direkt auf die Kastenkante und
liess die Bahn danach irgendwohin laufen. Das sah aus, als streife die
Linie den Kasten zufaellig, und wo zwei Punkte fast aufeinanderlagen,
warf die Kurve einen Zipfel. Beides zusammen war der Grund, warum die
Anbindung nicht stimmte.
Jetzt bekommt jedes Stueck vor dem Kasten einen Punkt auf gleicher Hoehe,
52 px daneben. Die Kurve laeuft dadurch waagerecht aus dem Kasten heraus
und waagerecht in den naechsten hinein: sie haengt sichtbar an ihm, statt
an ihm vorbeizukommen. */
function leitungsStueck(vonX, vonY, nachX, nachY, seite, abstand, zwischen) {
return [[vonX, vonY], [vonX + seite * abstand, vonY]]
.concat(zwischen)
.concat([[nachX + seite * abstand, nachY], [nachX, nachY]]);
}
function visProzesse() {
keim(20260813);
const W = 896, H = 730, HOCH = 62;
/* Die x-Werte sind so gewaehlt, dass die rechten Kanten dort landen, wo
die Leitung sie erwartet. Wer eine Beschriftung aendert, aendert die
Kastenbreite und muss die Ankerpunkte unten mitziehen. */
const chips = [
{ x: 34, y: 60, t: "E-Mails", g: glyBrief },
{ x: 104, y: 200, t: "Zettel im Auto", g: glyZettel },
{ x: 48, y: 340, t: "Tabellen", g: glyTabelle },
{ x: 128, y: 480, t: "Fotos auf dem Handy", g: glyHandy },
{ x: 60, y: 620, t: "Ordner im Regal", g: glyOrdner },
];
chips.forEach(c => {
c.w = Math.round(84 + c.t.length * 14.2);
c.r = c.x + c.w;
});
let raus = "";
// Rechte Kette: von rechter Kante zu rechter Kante, mit weiten Bogen.
const rechts = [
[[470, 34], [590, 72], [624, 150], [540, 186]],
[[576, 244], [672, 312], [604, 392], [492, 372], [432, 308]],
[[352, 398], [452, 424], [600, 406], [688, 470]],
[[664, 540], [708, 624], [606, 684], [478, 660]],
];
let leitung = "";
rechts.forEach((zw, i) => {
leitung += glatt(leitungsStueck(chips[i].r, chips[i].y, chips[i + 1].r,
chips[i + 1].y, 1, 52, zw)
.map(q => [q[0] + zit(2.5), q[1] + zit(2.5)]), false);
});
// Linke Kette: dort ist wenig Platz, also zwei knappe Bogen.
[[1, 2, [[24, 244], [14, 302]]], [3, 4, [[22, 522], [16, 576]]]].forEach(v => {
leitung += glatt(leitungsStueck(chips[v[0]].x, chips[v[0]].y, chips[v[1]].x,
chips[v[1]].y, -1, 34, v[2])
.map(q => [q[0] + zit(2), q[1] + zit(2)]), false);
});
/* Die Leitung traegt den Akzent. Gestrichelt und gelb heisst hier
gewachsen, durchgezogen und gelb auf Slide 5 heisst verbunden: dieselbe
Farbe, aber die Strichart trennt die beiden Aussagen. Etwas kraeftiger
als in Grau, weil eine unterbrochene Linie weniger Flaeche hat. */
raus += zug(leitung, { f: GELB, w: 2.9, op: .78, strichel: "11 13" });
[[700, 96, "blatt", 52], [770, 236, "bild", 46], [760, 430, "person", 50],
[250, 690, "blatt", 44]]
.forEach(k => { raus += zug(kachel(k[0], k[1], k[2], k[3]), { w: 2.5, op: .8 }); });
chips.forEach(c => {
const y = c.y - HOCH / 2;
raus += zug(chamfer(c.x, y, c.w, HOCH, 13), { w: 3.4 });
raus += zug(c.g(c.x + 34, c.y), { w: 2.6 });
raus += '<text x="' + (c.x + 64) + '" y="' + (c.y + 10) + '" ' +
'font-family="Manrope, sans-serif" font-size="27" font-weight="600" ' +
'letter-spacing="-0.01em" fill="' + TINTE + '">' + c.t + '</text>';
});
return '<svg viewBox="0 0 ' + W + ' ' + H + '" width="' + W + '" height="' + H +
'" xmlns="http://www.w3.org/2000/svg">' + raus + '</svg>';
}
/* ─── Slide 6: was nach der Anmeldung passiert ───────────────────────────
Uebernahme der Sektion "So geht\'s weiter" von der Website, in derselben
Handschrift wie Slide 5. Drei Schritte an einer Leitung, Wabe statt Kreis,
@@ -1669,15 +1839,7 @@
'<div class="karte-name"><span>Noah</span><small>CEO</small></div>' +
'</div>',
schiene: () =>
'<div class="vis-schiene">' +
'<div class="rail"><span>seit Jahren so</span></div>' +
'<div class="stufen">' +
kasten("Anfrage", "abtippen") + '<div class="verbund"></div>' +
kasten("Angebot", "noch mal abtippen") + '<div class="verbund"></div>' +
kasten("Rechnung", "und noch mal") +
'</div>' +
'</div>',
schiene: () => visProzesse(),
ersetzen: () =>
'<div class="vis-ersetzen">' +