diff --git a/animation/post9-animWebinar.mp4 b/animation/post9-animWebinar.mp4
index 21dfbd8..2a940b7 100644
Binary files a/animation/post9-animWebinar.mp4 and b/animation/post9-animWebinar.mp4 differ
diff --git a/post9.html b/post9.html
index 25dec40..5b542c7 100644
--- a/post9.html
+++ b/post9.html
@@ -4552,52 +4552,34 @@ if (location.search.indexOf("nur=anim") >= 0)
{ kuerzel: "DB", name: "David Bertram", rolle: "Produkt & Design" },
];
- /* Die vier Teile, Wort fuer Wort von „Was heute kommt“. Die Zeichen sind
- die Phosphor-Gegenstuecke zu den Lucide-Zeichen auf derselben Slide:
+ /* Die vier Teile, Wort fuer Wort von „Was heute kommt“. akzent ist das
+ Wort in Gelb, wie auf den Kapitel-Slides des Webinars. Die Zeichen sind
+ die Phosphor-Gegenstuecke zu den Lucide-Zeichen auf „Was heute kommt“:
Kanban fuer die Pipelines, ein Ablauf fuer die Automation, zwei Blasen
fuer den Chat, das Geschenk fuer die Ueberraschung. */
const WB_TEILE = [
- { rubrik: "Teil 1", zeichen: "kanban", zeilen: ["Von der Anfrage", "zum Auftrag"] },
- { rubrik: "Teil 2", zeichen: "tree-structure", zeilen: ["Das Herzstück:", "Automatisierung"] },
- { rubrik: "Teil 3", zeichen: "chats-circle", zeilen: ["Alles drumherum: Chat,", "Personal, Passwörter"] },
- { rubrik: "Zum Schluss", zeichen: "gift", zeilen: ["Eine Überraschung"] },
+ { rubrik: "Teil 1", zeichen: "kanban", akzent: "Auftrag", zeilen: ["Von der Anfrage", "zum Auftrag"] },
+ { rubrik: "Teil 2", zeichen: "tree-structure", akzent: "Automatisierung", zeilen: ["Das Herzstück:", "Automatisierung"] },
+ { rubrik: "Teil 3", zeichen: "chats-circle", akzent: "drumherum:", zeilen: ["Alles drumherum: Chat,", "Personal, Passwörter"] },
+ { rubrik: "Zum Schluss", zeichen: "gift", akzent: "Überraschung", zeilen: ["Eine Überraschung"] },
];
- /* Rot nur fuer die Live-Marke. Aus ui/theme.css von hivegrid-cloud:
- red-100, red-200, red-700 nach dem Muster der Marken in Post 8, der
- Punkt ist red-500. */
- const WB_ROT = { flaeche: "#FEE2E2", rand: "#FDCBCB", zeichen: "#C52020", punkt: "#ED4646" };
- /* Das Sechseck der Webinar-Slides: Gelb #FCE48A, Tinte als Rand. */
- const WB_WABE = "#FCE48A";
+ /* Markengelb fuer die Wabe in der Live-Marke, wie --accent-yellow. */
+ const WB_GELB = "#F1B729";
+ /* Die Farben der Kapitel-Slides im Webinar (quelle/slides/teil1.html):
+ dunkler Grund, Titel fast weiss, die Rubrik grau. */
+ const WB_DUNKEL = "#24242B", WB_HELL = "#FAFAFA", WB_GRAU = "#9D9DA0";
const WB_B = 720, WB_RAND = 34, WB_KOPF = 92;
let wbNr = 0;
- /* Die Live-Marke: Punkt, Wort, und um den Punkt ein Ring, der einmal pro
- Sekunde aufgeht. puls laeuft von 0 bis 1; ohne puls steht der Punkt
- still. */
- function wbLive(x, ym, puls) {
- const gr = 14, h = gr + 13, b = messen("Live", gr, 700) + gr * 1.9 + 14;
- let g = '';
- const px = x + 15;
- if (puls !== undefined && puls > 0 && puls < 1) {
- g += '';
- }
- g += '';
- g += uiText(px + 11, ym + gr * .36, "Live", gr, 700, WB_ROT.zeichen);
- return g;
- }
-
- /* Der Rahmen: Zeichen, Titel, Live-Marke, Trennlinie. Wie emRahmen in
- Post 8, nur ohne Reiter. */
+ /* Der Rahmen: Zeichen, Titel, Trennlinie. Wie emRahmen in Post 8, nur
+ ohne Reiter. Eine eigene Live-Marke gibt es nicht mehr: Der Titel sagt
+ schon „Live-Webinar“ (Dejan, 20.10.). */
function wbRahmen(h, inhalt, o) {
const B = WB_B + 2 * WB_RAND;
let g = ikon(o.zeichen, WB_RAND + 14, 33, 20, CHAT_TEXT);
g += uiText(WB_RAND + 32, 40, o.titel, 20, 800, CHAT_TEXT);
- g += wbLive(WB_RAND + 46 + messen(o.titel, 20, 800), 33, o.puls);
/* Rechts der Termin. Ohne ihn sagt das erste Element nur, worum es geht,
und nicht, wann. */
if (o.rechts) {
@@ -4610,28 +4592,105 @@ if (location.search.indexOf("nur=anim") >= 0)
return stapelKasten(B, h, 22, g);
}
- /* Das Sechseck mit Zeichen, wie auf „Was heute kommt“. */
- function wbWabe(x, y, s, zeichen) {
- const k = s / 56;
- const p = [[3, 28], [15.5, 6.4], [40.5, 6.4], [53, 28], [40.5, 49.6], [15.5, 49.6]]
- .map(q => n1(x + q[0] * k) + "," + n1(y + q[1] * k)).join(" ");
- return '' +
- ikon(zeichen, x + s / 2, y + s / 2, s * .42, CHAT_TEXT);
+ /* Das Wabenmuster der Kapitel-Slides (bilder/wabe-ecke.png im Webinar):
+ gelbe G-Waben, oben rechts am kraeftigsten, nach links unten auslaufend.
+ Hier als Vektoren nachgebaut, damit jedes Videobild gleich scharf ist
+ und kein Bild nachladen muss. Die Waben stehen einmal fest; das Auslaufen
+ macht eine Maske mit Verlauf, die maske() je Bild neu benennt. */
+ const WB_MUSTER = (() => {
+ const G = "384.5,166.5 336.4,83.2 192.2,166.5 288.3,166.5 240.3,249.7 144.2,249.7 96.1,166.5 144.2,83.2 336.4,83.2 298,16.8 288.3,0 96.1,0 0,166.5 96.1,332.9 288.3,332.9";
+ const B = 50, S = B / 384.5, H = 332.9 * S, L = 7;
+ const DX = 0.75 * B + L, DY = H + L * 1.1;
+ let g = "";
+ for (let sp = 0; sp * DX < 720 + B; sp++) {
+ for (let z = -1; z * DY < 430; z++) {
+ const x = 720 - B - sp * DX, y = z * DY + (sp % 2 ? DY / 2 : 0);
+ if (x < 200 - B || y > 320) continue;
+ g += '';
+ }
+ }
+ return g;
+ })();
+ /* Das zweite Muster der Webinar-Slides (waben.py, Slides „noah“ und
+ „problem“): weisse Waben mit grauem Rand auf hellem Grund, dazwischen
+ einzelne gelbe. Fuer die Folien nach Teil 1, damit die Titelfolie
+ dunkel bleibt und die anderen sich davon abheben. Spitze Waben wie
+ dort, die gelben stehen ausserhalb der Maske und bleiben voll. */
+ const WB_WABEN_HELL = (() => {
+ const R = 26, DX = Math.sqrt(3) * R, DY = 1.5 * R;
+ const ecken = (x, y) => [-90, -30, 30, 90, 150, 210]
+ .map(w => n1(x + R * Math.cos(w * Math.PI / 180)) + "," + n1(y + R * Math.sin(w * Math.PI / 180))).join(" ");
+ const zellen = [];
+ for (let j = 0; j * DY < 330; j++) {
+ for (let i = 0; i * DX < 720; i++) {
+ const x = 720 - i * DX - (j % 2 ? DX / 2 : 0), y = j * DY;
+ if (x > 230) zellen.push([x, y]);
+ }
+ }
+ const naechste = (zx, zy) => zellen.reduce((a, z) => Math.hypot(z[0] - zx, z[1] - zy) < Math.hypot(a[0] - zx, a[1] - zy) ? z : a);
+ const gelb = [naechste(470, 40), naechste(400, 140), naechste(690, 315)];
+ return {
+ waben: zellen.filter(z => !gelb.includes(z)).map(z => '').join(""),
+ gelb: gelb.map(z => '').join(""),
+ };
+ })();
+
+ function wbMaske(id) {
+ const verlauf = (vid, staerke) => '' +
+ '' +
+ '';
+ const maske = (mid, vid) => '' +
+ '';
+ return verlauf(id + "v", ".45") + maske(id, id + "v") + verlauf(id + "hv", "1") + maske(id + "h", id + "hv");
}
- /* Eine Folie auf der Buehne. Sechseck oben rechts, Rubrik oben links,
- der Titel unten links: dieselbe Diagonale wie auf den Kapitel-Slides
- des Webinars. */
+ /* Das Zeichen des Teils in einer grossen gelben Wabe oben rechts. Sie
+ sitzt im Muster wie eine hervorgehobene Zelle: Ein Rand in der Farbe
+ des Grunds raeumt die Waben darunter frei. Auf der dunklen Folie flach
+ wie die G-Waben, auf den hellen spitz wie die Zellen dort. */
+ function wbIkonWabe(zeichen, hell) {
+ const cx = 620, cy = 118, R = 58, rand = 9;
+ const winkel = hell ? [-90, -30, 30, 90, 150, 210] : [0, 60, 120, 180, 240, 300];
+ const ecken = r => winkel.map(w => n1(cx + r * Math.cos(w * Math.PI / 180)) + "," +
+ n1(cy + r * Math.sin(w * Math.PI / 180))).join(" ");
+ return '' +
+ '' +
+ ikon(zeichen, cx, cy, R * .86, CHAT_TEXT);
+ }
+
+ /* Eine Titelzeile, das Akzentwort in Gelb. */
+ function wbZeile(x, y, text, akzent, gr, farbe) {
+ const i = akzent ? text.indexOf(akzent) : -1;
+ const stueck = (s, farbe) => s ? '' + wfEsc(s) + '' : "";
+ const inhalt = i < 0 ? wfEsc(text) : stueck(text.slice(0, i), farbe) + stueck(akzent, WB_GELB) +
+ stueck(text.slice(i + akzent.length), farbe);
+ return '' + inhalt + '';
+ }
+
+ /* Eine Folie auf der Buehne, im Look der Webinar-Slides: oben rechts das
+ Wabenmuster, oben links die Rubrik, unten links der Titel mit einem Wort
+ in Gelb. Teil 1 ist die Titelfolie, dunkel mit G-Waben wie die
+ Kapitel-Slides. Die drei danach sind hell mit dem zweiten Muster
+ (Dejan, 20.10.). */
const WB_BUEHNE_H = 430;
- function wbFolie(x0, teil) {
- let g = wbWabe(x0 + WB_B - 44 - 124, 36, 124, teil.zeichen);
- g += uiText(x0 + 48, 78, teil.rubrik.toUpperCase(), 17, 800, CHAT_TEXT3, { sperr: "0.13em" });
+ function wbFolie(x0, teil, maske, hell) {
+ let g = '';
+ if (hell) {
+ g += '';
+ g += '' + WB_WABEN_HELL.waben + '';
+ g += '' + WB_WABEN_HELL.gelb + '';
+ } else {
+ g += '';
+ g += '' + WB_MUSTER + '';
+ }
+ g += wbIkonWabe(teil.zeichen, hell);
+ g += uiText(48, 78, teil.rubrik.toUpperCase(), 17, 800, hell ? CHAT_TEXT3 : WB_GRAU, { sperr: "0.13em" });
const zh = 56, unten = WB_BUEHNE_H - 94;
teil.zeilen.forEach((z, i) => {
- g += uiText(x0 + 48, unten - (teil.zeilen.length - 1 - i) * zh, z, 48, 800, CHAT_TEXT);
+ g += wbZeile(48, unten - (teil.zeilen.length - 1 - i) * zh, z, teil.akzent, 48, hell ? CHAT_TEXT : WB_HELL);
});
- return g;
+ return g + '';
}
/* Eine Kachel fuer einen Sprecher: Foto, Name, Rolle. spricht blendet den
@@ -4668,22 +4727,19 @@ if (location.search.indexOf("nur=anim") >= 0)
sich je Teil ein Abschnitt der Leiste.
Unter der Buehne die beiden Sprecher. Wer redet, hat den dunklen Rand.
- Die Reihenfolge ist die aus dem Skript: Jedes Kapitel eroeffnet Noah,
- dann uebernimmt David.
+ Noah die erste Haelfte, David die zweite.
Alles, was sich wiederholt, laeuft in ganzen Perioden ueber die acht
- Sekunden: der Puls der Live-Marke achtmal, die Balken drei-, vier- und
- fuenfmal je Teil. Ein Video, das sich auf Instagram
- wiederholt, springt dann nur bei der Folie und nicht beim Puls. */
+ Sekunden, die Balken drei-, vier- und fuenfmal je Teil. Ein Video, das
+ sich auf Instagram wiederholt, springt dann nur bei der Folie. */
function animWebinar(j, t) {
const n = WB_TEILE.length, abschnitt = 1 / n, schub = .045;
/* Welche Folie steht, und wie weit der Schub zur naechsten ist. */
let g = "";
- const id = "wbbuehne" + (++wbNr);
+ const id = "wbbuehne" + (++wbNr), maske = id + "m";
g += '';
- g += '';
+ '"/>' + wbMaske(maske);
+ g += '';
let folien = "";
for (let i = 0; i < n; i++) {
@@ -4693,27 +4749,33 @@ if (location.search.indexOf("nur=anim") >= 0)
const raus_ = i === n - 1 ? 0 : daempfen(stufe(t, (i + 1) * abschnitt - schub, (i + 1) * abschnitt + schub));
const x0 = (1 - rein) * WB_B - raus_ * WB_B;
if (x0 >= WB_B || x0 <= -WB_B) continue;
- folien += wbFolie(x0, WB_TEILE[i]);
+ folien += wbFolie(x0, WB_TEILE[i], maske, i > 0);
}
g += '' + folien + '';
/* Die Leiste: vier Abschnitte, jeder fuellt sich, solange sein Teil
steht. */
const LX = 48, LB = WB_B - 96, LL = 8, sb = (LB - (n - 1) * LL) / n, ly = WB_BUEHNE_H - 40;
+ /* Die Spur ist auf der dunklen Titelfolie weiss und durchscheinend, auf
+ den hellen grau. Sie wechselt mit dem Schub zu Teil 2. */
+ const hellAnteil = daempfen(stufe(t, abschnitt - schub, abschnitt + schub));
for (let i = 0; i < n; i++) {
const sx = LX + i * (sb + LL);
g += '';
+ '" height="6" rx="3" fill="#FFFFFF" fill-opacity="' + (.16 * (1 - hellAnteil)).toFixed(3) + '"/>';
+ if (hellAnteil > 0) g += '';
const p = stufe(t, i * abschnitt, (i + 1) * abschnitt);
if (p > 0) g += '';
+ '" height="6" rx="3" fill="' + WB_GELB + '"/>';
}
- /* Die Sprecher. Im Abschnitt eines Teils redet erst Noah, ab etwas
- ueber der Haelfte David. Der Wechsel blendet ueber, damit nicht beide
+ /* Die Sprecher. Noah redet bei Teil 1 und 2, David bei Teil 3 und 4.
+ Gewechselt wird nur einmal, mit dem Schub zur dritten Folie, und am
+ Ende des Loops zurueck. Vorher wechselte es in jedem Teil, das war zu
+ unruhig (Dejan, 20.10.). Der Wechsel blendet ueber, damit nicht beide
Raender gleichzeitig hart umspringen. */
- const imTeil = (t % abschnitt) / abschnitt;
- const david = stufe(imTeil, .52, .62);
+ const david = daempfen(stufe(t, .5 - schub, .5 + schub));
const noah = 1 - david;
const sy = WB_BUEHNE_H + 20, kb = (WB_B - 16) / 2;
const phase = t * n;
@@ -4721,7 +4783,7 @@ if (location.search.indexOf("nur=anim") >= 0)
g += wbSprecher(kb + 16, sy, kb, WB_SPRECHER[1], david, phase);
const h = WB_KOPF + WB_BUEHNE_H + 20 + 84 + WB_RAND;
- return wbRahmen(h, g, { zeichen: "video-camera", titel: "Live-Webinar", puls: (t * 8) % 1,
+ return wbRahmen(h, g, { zeichen: "video-camera", titel: "Live-Webinar",
rechts: WEBINAR.datum + ", " + WEBINAR.uhrzeit + " Uhr" });
}