Nur noch das Raster als Grund, Menueleiste, Post 2
Der Grund ist fest das Raster. Raus sind die vier Formen-Bausteine, die grosse
G-Marke, das Wabenraster samt seinem Kachel-Erzeuger, die Punkte und die
Musterauswahl mit ihrer Taste. Ebenso das durchgehende Band: Sechsecke auf den
Naehten, Band und G-Marke, CSS, Schalter und Taste.
Beim Aufraeumen war zwischenzeitlich ".bg > * { display: none; }" mit
verschwunden. Diese eine Zeile hatte das Band die ganze Zeit verdeckt, eine
Einblende-Regel gab es dafuer naemlich nie. Ohne sie schwebten Sechsecke und
G-Marke ueber den Slides.
Die Projektauswahl ist eine Menueleiste ueber die volle Breite: Projekt,
Datei, Bearbeiten, Slide, Ansicht. Sie fuehrt nichts selbst aus, sondern
betaetigt die vorhandenen Schalter im Bedienfeld, damit jedes Verhalten an
genau einer Stelle steht. Haken und graue Eintraege liest sie beim Oeffnen aus
denselben Schaltern.
post2.html ist eine Kopie von post1.html bis auf Titel, Ueberschrift und
Projektschluessel.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
92529a8c47
commit
57d1f4c540
2 files changed
+3810
-222
No files matched your search
+199
-222
@@ -30,9 +30,53 @@
|
||||
body {
|
||||
font-family: 'Manrope', system-ui, sans-serif;
|
||||
background: #17181F; color: #E8EAEE;
|
||||
height: 100vh; overflow: hidden; display: flex;
|
||||
height: 100vh; overflow: hidden;
|
||||
display: flex; flex-direction: column;
|
||||
}
|
||||
|
||||
/* ─── Menueleiste ────────────────────────────────────────────────────────
|
||||
Statt einer Knopfreihe fuer die Projekte eine Leiste wie in einem
|
||||
Bildprogramm. Sie bedient keine eigene Logik, sondern klickt die
|
||||
vorhandenen Schalter im Bedienfeld an: sonst gaebe es zwei Wahrheiten
|
||||
ueber denselben Zustand. */
|
||||
.menubar {
|
||||
flex: none; display: flex; align-items: stretch; gap: 2px;
|
||||
height: 34px; padding: 0 8px;
|
||||
background: #14161C; border-bottom: 1px solid #24262F;
|
||||
font-size: 13px; user-select: none; position: relative; z-index: 60;
|
||||
}
|
||||
.menubar .marke {
|
||||
display: flex; align-items: center; padding: 0 12px 0 4px;
|
||||
font-weight: 800; letter-spacing: -0.01em; color: #E8EAEE;
|
||||
}
|
||||
.menu { position: relative; }
|
||||
.menu > button {
|
||||
height: 100%; padding: 0 11px; cursor: pointer;
|
||||
background: none; border: 0; color: #C7CCD6;
|
||||
font-family: inherit; font-size: 13px;
|
||||
}
|
||||
.menu > button:hover { background: #1D1F26; }
|
||||
.menu[data-offen="ja"] > button { background: #262932; color: #fff; }
|
||||
.menu > .liste { display: none; }
|
||||
.menu[data-offen="ja"] > .liste {
|
||||
display: block; position: absolute; top: 100%; left: 0;
|
||||
min-width: 232px; padding: 5px;
|
||||
background: #1D1F26; border: 1px solid #2E313B; border-radius: 9px;
|
||||
}
|
||||
.menu .liste button {
|
||||
display: flex; width: 100%; align-items: center; gap: 14px;
|
||||
padding: 6px 9px; cursor: pointer; text-align: left;
|
||||
background: none; border: 0; border-radius: 6px;
|
||||
color: #C7CCD6; font-family: inherit; font-size: 13px;
|
||||
}
|
||||
.menu .liste button:hover { background: #2A2D36; color: #fff; }
|
||||
.menu .liste button:disabled { opacity: .38; cursor: default; background: none; }
|
||||
.menu .liste button .kurz { margin-left: auto; color: #6E7480; font-size: 11.5px; }
|
||||
.menu .liste button .haken { width: 12px; color: var(--accent-yellow); }
|
||||
.menu .liste hr { height: 1px; margin: 5px 4px; background: #2E313B; border: 0; }
|
||||
|
||||
.arbeitsflaeche { flex: 1; display: flex; min-height: 0; }
|
||||
|
||||
/* Inhaltsfelder der gewaehlten Slide. Eine Spalte, damit lange Texte nicht
|
||||
in einer schmalen Zelle kleben. */
|
||||
#inhalt { display: flex; flex-direction: column; gap: 4px; }
|
||||
@@ -96,7 +140,7 @@
|
||||
|
||||
/* ─── Control panel ──────────────────────────────────────────────────── */
|
||||
.panel {
|
||||
width: 306px; flex: none; height: 100vh; overflow-y: auto;
|
||||
width: 306px; flex: none; height: 100%; overflow-y: auto;
|
||||
padding: 28px 22px 40px 28px;
|
||||
border-right: 1px solid #24262F; background: #17181F;
|
||||
}
|
||||
@@ -287,121 +331,20 @@
|
||||
font-family: 'Manrope', system-ui, sans-serif;
|
||||
}
|
||||
|
||||
/* ─── Background layers ──────────────────────────────────────────────────
|
||||
Five interchangeable grounds. Shapes are built from the brand geometry
|
||||
(chamfered blocks + flat-top hexagons) in --dark-bg, the colour of the dark
|
||||
story section on the site. */
|
||||
/* ─── Grund ──────────────────────────────────────────────────────────────
|
||||
Ein einziger Grund: das Raster. Formen, Waben, Punkte und die grosse
|
||||
G-Marke sind raus, ebenso das durchgehende Band mit den Sechsecken auf
|
||||
den Naehten. Einstellbar bleibt nur die Staerke. */
|
||||
.bg { position: absolute; inset: 0; pointer-events: none; z-index: 0; overflow: hidden; }
|
||||
.slide[data-int="dezent"] .bg { --int-mul: .55; }
|
||||
.slide[data-int="kraeftig"] .bg { --int-mul: 1; }
|
||||
|
||||
.bg > * { display: none; }
|
||||
.slide[data-bg="formen"] .layer-shapes,
|
||||
.slide[data-bg="formen-g"] .layer-shapes,
|
||||
.slide[data-bg="formen-g"] .layer-gmark,
|
||||
.slide[data-bg="nur-g"] .layer-shapes,
|
||||
.slide[data-bg="nur-g"] .layer-gmark,
|
||||
.slide[data-bg="waben"] .layer-waben,
|
||||
.slide[data-bg="punkte"] .layer-punkte,
|
||||
.slide[data-bg="raster"] .layer-raster { display: block; }
|
||||
|
||||
.layer-shapes, .layer-waben, .layer-punkte, .layer-raster {
|
||||
position: absolute; inset: 0; width: 100%; height: 100%;
|
||||
}
|
||||
.layer-gmark { inset: auto; }
|
||||
.slide[data-bg="nur-g"] .sh-block { display: none; }
|
||||
.layer-raster { position: absolute; inset: 0; width: 100%; height: 100%; }
|
||||
|
||||
/* Optische Ausrückung des Tags: Der Kasten steht bündig zur Inhaltskante,
|
||||
sein TEXT dadurch um die 20 px Innenabstand eingerückt gegenüber der
|
||||
Headline. Das negative Margin holt den Text auf dieselbe Linie. Zum
|
||||
Vergleichen umschaltbar. */
|
||||
|
||||
.sh { position: absolute; }
|
||||
|
||||
/* Two large forms anchored to opposite corners and mostly off canvas, plus
|
||||
the yellow hex as the one warm accent. Everything stays clear of the copy:
|
||||
shapes crossing the headline are what made an earlier version look thrown
|
||||
together. */
|
||||
.sh-block {
|
||||
top: -300px; right: -290px; width: 760px; height: 760px;
|
||||
background: var(--shape-fill);
|
||||
transform: rotate(-14deg);
|
||||
clip-path: polygon(
|
||||
74px 0, calc(100% - 74px) 0, 100% 74px, 100% calc(100% - 74px),
|
||||
calc(100% - 74px) 100%, 74px 100%, 0 calc(100% - 74px), 0 74px
|
||||
);
|
||||
}
|
||||
.sh-hex-line {
|
||||
bottom: -300px; left: -260px; width: 660px; height: 572px;
|
||||
opacity: var(--int-mul, 1);
|
||||
border: 14px solid var(--shape-line);
|
||||
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
|
||||
}
|
||||
.sh-hex-accent {
|
||||
top: 268px; left: -66px; width: 172px; height: 149px;
|
||||
opacity: var(--int-mul, 1);
|
||||
background: var(--shape-accent);
|
||||
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
|
||||
}
|
||||
.sh-hex-small {
|
||||
bottom: 296px; right: -40px; width: 108px; height: 94px;
|
||||
opacity: var(--int-mul, 1);
|
||||
background: var(--shape-accent-2);
|
||||
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
|
||||
}
|
||||
|
||||
/* Oversized G behind the device, cropped by whatever sits in front of it, so
|
||||
only its top peeks out. Same idea as the watermark on the dark comparison
|
||||
card on the site, just in grey. Lives in the background layer (z-index 0),
|
||||
so the mockup always covers its lower half. */
|
||||
.layer-gmark {
|
||||
position: absolute; left: 50%; top: 400px;
|
||||
width: 880px; height: auto;
|
||||
transform: translateX(-50%);
|
||||
color: var(--gmark-color);
|
||||
opacity: var(--int-mul, 1);
|
||||
}
|
||||
|
||||
/* ─── Durchgehendes Carousel ──────────────────────────────────────────────
|
||||
Der Post ist ein einziges durchgehendes Blatt, das in 1080er Fenster
|
||||
geschnitten wird. Seine Breite folgt der Anzahl der Slides (--sheet-w). Jede Slide zeigt ihren Ausschnitt, indem die
|
||||
Ebene um index * 1080 nach links verschoben wird. Elemente auf den Nähten
|
||||
werden dadurch zerschnitten und laufen auf der nächsten Slide weiter. */
|
||||
.continuum {
|
||||
position: absolute; top: 0; height: 100%;
|
||||
left: calc(var(--slide-i, 0) * -1080px);
|
||||
width: var(--sheet-w, 5400px);
|
||||
pointer-events: none;
|
||||
opacity: var(--int-mul, 1);
|
||||
}
|
||||
.slide[data-cont="aus"] .continuum { display: none; }
|
||||
.continuum > * { position: absolute; }
|
||||
|
||||
/* Sechsecke sitzen mittig auf den Nähten (1080, 2160, 3240, 4320) und werden
|
||||
dort halbiert. Das ist das deutlichste Signal, dass es weitergeht. */
|
||||
.ct-hex {
|
||||
background: var(--shape-fill);
|
||||
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
|
||||
}
|
||||
.ct-hex-line {
|
||||
border: 13px solid var(--shape-line);
|
||||
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
|
||||
}
|
||||
/* Ein Band über die volle Breite: die Klammer, die alle fünf zusammenhält. */
|
||||
.ct-band {
|
||||
left: 0; width: var(--sheet-w, 5400px); height: 54px; bottom: 96px;
|
||||
background: var(--shape-line);
|
||||
}
|
||||
.ct-g { color: var(--gmark-color); }
|
||||
|
||||
.layer-waben { color: var(--pat-color); opacity: calc(var(--pat-strength) * var(--int-mul, 1)); }
|
||||
|
||||
.layer-punkte {
|
||||
background-image: radial-gradient(circle, var(--pat-color) 3px, transparent 3px);
|
||||
background-size: 52px 52px;
|
||||
opacity: calc(var(--pat-strength) * var(--int-mul, 1));
|
||||
}
|
||||
|
||||
.layer-raster {
|
||||
background-image:
|
||||
linear-gradient(var(--pat-color) 2px, transparent 2px),
|
||||
@@ -780,8 +723,6 @@
|
||||
--frame-bg: rgba(255,255,255,.11);
|
||||
--shape-fill: #414252;
|
||||
--shape-line: rgba(255,255,255,.10);
|
||||
--shape-accent: var(--accent-yellow);
|
||||
--shape-accent-2: rgba(255,255,255,.14);
|
||||
--pat-color: #FFFFFF; --pat-strength: .07;
|
||||
--gmark-color: rgba(255,255,255,.13);
|
||||
--guide-line: rgba(255,255,255,.16);
|
||||
@@ -802,8 +743,6 @@
|
||||
--frame-bg: #E8EBF0;
|
||||
--shape-fill: var(--dark-bg);
|
||||
--shape-line: rgba(48,49,61,.13);
|
||||
--shape-accent: var(--accent-yellow);
|
||||
--shape-accent-2: rgba(48,49,61,.16);
|
||||
--pat-color: #30313D; --pat-strength: .07;
|
||||
--gmark-color: rgba(48,49,61,.16);
|
||||
--guide-line: rgba(48,49,61,.20);
|
||||
@@ -815,6 +754,73 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="menubar" id="menubar">
|
||||
<span class="marke">HiveGrid</span>
|
||||
|
||||
<div class="menu" data-menu="projekt">
|
||||
<button type="button">Projekt</button>
|
||||
<div class="liste">
|
||||
<button type="button" data-gehe="./post1.html">Post 1</button>
|
||||
<button type="button" data-gehe="./post2.html">Post 2</button>
|
||||
<hr>
|
||||
<button type="button" data-klick="snap-save">Stand merken</button>
|
||||
<button type="button" data-klick="snap-load">Zurück zum gemerkten Stand</button>
|
||||
<hr>
|
||||
<button type="button" data-klick="forget">Projekt zurücksetzen</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="menu" data-menu="datei">
|
||||
<button type="button">Datei</button>
|
||||
<div class="liste">
|
||||
<button type="button" data-klick="bild-waehlen">Bild importieren</button>
|
||||
<hr>
|
||||
<button type="button" data-klick="dl-png">Diese Slide laden<span class="kurz">D</span></button>
|
||||
<button type="button" data-klick="dl-all">Alle Slides als ZIP<span class="kurz">A</span></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="menu" data-menu="bearbeiten">
|
||||
<button type="button">Bearbeiten</button>
|
||||
<div class="liste">
|
||||
<button type="button" data-tun="undo">Rückgängig<span class="kurz">⌘Z</span></button>
|
||||
<button type="button" data-tun="redo">Wiederherstellen<span class="kurz">⇧⌘Z</span></button>
|
||||
<hr>
|
||||
<button type="button" data-opt="editmodes:e:an">Bearbeiten an<span class="kurz">E</span></button>
|
||||
<button type="button" data-opt="editmodes:e:aus">Bearbeiten aus</button>
|
||||
<hr>
|
||||
<button type="button" data-klick="reset-one">Element auf Standard</button>
|
||||
<button type="button" data-klick="reset-all">Alles auf Standard</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="menu" data-menu="slide">
|
||||
<button type="button">Slide</button>
|
||||
<div class="liste">
|
||||
<button type="button" data-klick="slide-neu">Neu dahinter</button>
|
||||
<button type="button" data-klick="slide-kopie">Kopieren</button>
|
||||
<button type="button" data-klick="slide-weg">Löschen</button>
|
||||
<hr>
|
||||
<button type="button" data-klick="slide-links">Nach vorn</button>
|
||||
<button type="button" data-klick="slide-rechts">Nach hinten</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="menu" data-menu="ansicht">
|
||||
<button type="button">Ansicht</button>
|
||||
<div class="liste">
|
||||
<button type="button" data-opt="views:w:streifen">Streifen<span class="kurz">W</span></button>
|
||||
<button type="button" data-opt="views:w:einzeln">Einzeln</button>
|
||||
<hr>
|
||||
<button type="button" data-klick="zoom-fit">Einpassen<span class="kurz">0</span></button>
|
||||
<button type="button" data-klick="zoom-in">Größer<span class="kurz">+</span></button>
|
||||
<button type="button" data-klick="zoom-out">Kleiner<span class="kurz">−</span></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arbeitsflaeche">
|
||||
|
||||
<aside class="panel">
|
||||
<h1>Post 1 · Lösung</h1>
|
||||
<p class="sub"><span id="kopfzeile">Carousel · 1080 × 1350 px</span><span class="saved" id="saved"></span><br><button class="forget" id="forget">Projekt zurücksetzen</button></p>
|
||||
@@ -891,27 +897,6 @@
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="group" data-grp="durchgehend-alle-slides">
|
||||
<summary>Durchgehend (alle Slides)</summary>
|
||||
<div class="opts" id="conts">
|
||||
<button data-c="an" aria-pressed="false">An</button>
|
||||
<button data-c="aus" aria-pressed="true">Aus</button>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="group" data-grp="muster-nur-diese-slide">
|
||||
<summary>Muster (nur diese Slide)</summary>
|
||||
<div class="opts three" id="bgs">
|
||||
<button data-b="formen" aria-pressed="true">Formen</button>
|
||||
<button data-b="formen-g" aria-pressed="false">Formen + G</button>
|
||||
<button data-b="nur-g" aria-pressed="false">Nur G</button>
|
||||
<button data-b="waben" aria-pressed="false">Waben</button>
|
||||
<button data-b="punkte" aria-pressed="false">Punkte</button>
|
||||
<button data-b="raster" aria-pressed="false">Raster</button>
|
||||
<button data-b="aus" aria-pressed="false">Aus</button>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="group" data-grp="intensit-t">
|
||||
<summary>Intensität</summary>
|
||||
<div class="opts" id="ints">
|
||||
@@ -959,8 +944,8 @@
|
||||
<summary>Tastatur</summary>
|
||||
<div class="keys">
|
||||
<kbd>←</kbd><kbd>→</kbd> Slide · <kbd>V</kbd> Variante<br>
|
||||
<kbd>L</kbd> Layout · <kbd>M</kbd> Muster · <kbd>I</kbd> Intensität<br>
|
||||
<kbd>C</kbd> Durchgehend · <kbd>W</kbd> Ansicht · <kbd>G</kbd> Tag<br>
|
||||
<kbd>L</kbd> Layout · <kbd>I</kbd> Intensität<br>
|
||||
<kbd>W</kbd> Ansicht · <kbd>G</kbd> Tag<br>
|
||||
<kbd>R</kbd> Bildrahmen<br>
|
||||
<kbd>T</kbd> Perspektive<br>
|
||||
<kbd>E</kbd> Bearbeiten · Pfeile verschieben (<kbd>⇧</kbd> = 10 px)<br>
|
||||
@@ -1003,6 +988,7 @@
|
||||
</div>
|
||||
<div id="el-inhalt"></div>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<script src="./vendor/html-to-image.js"></script>
|
||||
<script src="./vendor/jszip.min.js"></script>
|
||||
@@ -1239,7 +1225,7 @@
|
||||
let editMode = "aus";
|
||||
|
||||
let current = 0;
|
||||
let variant = "dunkel", tilt = "an", superSample = 2, continuous = "aus", view = "streifen", tagOut = "an", frameStyle = "chamfer";
|
||||
let variant = "dunkel", tilt = "an", superSample = 2, view = "streifen", tagOut = "an", frameStyle = "chamfer";
|
||||
|
||||
/* ─── Projektstand ────────────────────────────────────────────────────────
|
||||
Alles, was am Projekt hängt, wird gespeichert: Einstellungen, Layouts,
|
||||
@@ -1253,7 +1239,7 @@
|
||||
|
||||
function currentState() {
|
||||
return {
|
||||
v: STATE_V, variant, tilt, superSample, continuous, view, tagOut, frameStyle,
|
||||
v: STATE_V, variant, tilt, superSample, view, tagOut, frameStyle,
|
||||
current, layoutState, bgState, edits,
|
||||
// Welche Slides der Post ueberhaupt hat. Ohne das waere eine selbst
|
||||
// angelegte Slide nach dem Neuladen weg.
|
||||
@@ -1380,7 +1366,6 @@
|
||||
press("variants", "v", variant);
|
||||
press("tilts", "t", tilt);
|
||||
press("quality", "q", String(superSample));
|
||||
press("conts", "c", continuous);
|
||||
press("tagouts", "o", tagOut);
|
||||
press("frames", "f", frameStyle);
|
||||
press("views", "w", view);
|
||||
@@ -1511,7 +1496,6 @@
|
||||
variant = d.variant || variant;
|
||||
tilt = d.tilt || tilt;
|
||||
superSample = d.superSample || superSample;
|
||||
continuous = d.continuous || continuous;
|
||||
view = d.view || view;
|
||||
tagOut = d.tagOut || tagOut;
|
||||
frameStyle = d.frameStyle || frameStyle;
|
||||
@@ -1538,7 +1522,8 @@
|
||||
.then(() => location.reload());
|
||||
}
|
||||
// Per-slide so a single slide can carry a different ground.
|
||||
const bgState = SLIDES.map(() => ({ bg: "formen", int: "dezent" }));
|
||||
// Der Grund ist fest das Raster. Einstellbar bleibt nur seine Staerke.
|
||||
const bgState = SLIDES.map(() => ({ bg: "raster", int: "dezent" }));
|
||||
// Each slide picks its own layout from its own catalogue.
|
||||
const layoutState = SLIDES.map(sl => sl.layouts[0].id);
|
||||
// Every asset is inlined once at boot, so re-rendering a layout stays synchronous.
|
||||
@@ -1603,74 +1588,13 @@
|
||||
'<circle cx="12" cy="5" r="1.9"/><circle cx="12" cy="12" r="1.9"/>' +
|
||||
'<circle cx="12" cy="19" r="1.9"/></svg>';
|
||||
|
||||
const SVG_NS = "http://www.w3.org/2000/svg";
|
||||
const G_POINTS = "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 G_W = 384.5, G_H = 332.9;
|
||||
|
||||
// Positionen im 5400er Raum. Die Nähte liegen auf 1080 / 2160 / 3240 / 4320.
|
||||
const CONTINUUM_HTML =
|
||||
'<div class="continuum">' +
|
||||
'<div class="ct-hex" style="left:870px; top:210px; width:420px; height:364px"></div>' +
|
||||
'<div class="ct-hex-line" style="left:1935px; top:930px; width:450px; height:390px"></div>' +
|
||||
'<div class="ct-hex" style="left:2980px; top:150px; width:520px; height:450px"></div>' +
|
||||
'<div class="ct-hex-line" style="left:4130px; top:860px; width:380px; height:329px"></div>' +
|
||||
'<div class="ct-band"></div>' +
|
||||
'<svg class="ct-g" style="left:1840px; top:420px; width:640px" ' +
|
||||
'viewBox="0 0 384.5 332.9" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">' +
|
||||
'<polygon fill="currentColor" points="' + G_POINTS + '"/></svg>' +
|
||||
'</div>';
|
||||
|
||||
const BG_HTML =
|
||||
'<div class="bg">' + CONTINUUM_HTML +
|
||||
'<div class="layer-shapes">' +
|
||||
'<div class="sh sh-block"></div>' +
|
||||
'<div class="sh sh-hex-line"></div>' +
|
||||
'<div class="sh sh-hex-accent"></div>' +
|
||||
'<div class="sh sh-hex-small"></div>' +
|
||||
'</div>' +
|
||||
'<svg class="layer-gmark" viewBox="0 0 384.5 332.9" aria-hidden="true" ' +
|
||||
'xmlns="http://www.w3.org/2000/svg"><polygon fill="currentColor" points="' +
|
||||
G_POINTS + '"/></svg>' +
|
||||
'<svg class="layer-waben" aria-hidden="true"></svg>' +
|
||||
'<div class="layer-punkte"></div>' +
|
||||
'<div class="bg">' +
|
||||
'<div class="layer-raster"></div>' +
|
||||
'</div>';
|
||||
|
||||
/* Seamless flat-top honeycomb tile, generated from the same G polygon as the
|
||||
logo mark. Columns step by 3/4 of the hex width and neighbouring columns sit
|
||||
half a row apart, so one tile is two columns wide and one row high. The
|
||||
copies hanging past the tile edges are what make the repeat seamless. */
|
||||
function buildWaben(svg, uid) {
|
||||
const colStep = G_W * 0.75, rowStep = G_H;
|
||||
const tileW = colStep * 2, tileH = rowStep;
|
||||
const centres = [
|
||||
[0, 0], [tileW, 0], [0, tileH], [tileW, tileH],
|
||||
[colStep, rowStep / 2], [colStep, -rowStep / 2], [colStep, tileH + rowStep / 2],
|
||||
];
|
||||
const id = "waben-" + uid;
|
||||
const defs = document.createElementNS(SVG_NS, "defs");
|
||||
const pat = document.createElementNS(SVG_NS, "pattern");
|
||||
pat.setAttribute("id", id);
|
||||
pat.setAttribute("patternUnits", "userSpaceOnUse");
|
||||
pat.setAttribute("width", tileW);
|
||||
pat.setAttribute("height", tileH);
|
||||
pat.setAttribute("patternTransform", "scale(0.46)");
|
||||
for (const [cx, cy] of centres) {
|
||||
const poly = document.createElementNS(SVG_NS, "polygon");
|
||||
poly.setAttribute("points", G_POINTS);
|
||||
poly.setAttribute("fill", "currentColor");
|
||||
poly.setAttribute("transform", "translate(" + (cx - G_W / 2) + "," + (cy - G_H / 2) + ")");
|
||||
pat.appendChild(poly);
|
||||
}
|
||||
defs.appendChild(pat);
|
||||
svg.appendChild(defs);
|
||||
const rect = document.createElementNS(SVG_NS, "rect");
|
||||
rect.setAttribute("width", "100%");
|
||||
rect.setAttribute("height", "100%");
|
||||
rect.setAttribute("fill", "url(#" + id + ")");
|
||||
svg.appendChild(rect);
|
||||
}
|
||||
|
||||
function contentHtml(s, i) {
|
||||
if (s.type === "feature") {
|
||||
return '<p class="badge">' + s.eyebrow + '</p>' +
|
||||
@@ -1890,13 +1814,11 @@
|
||||
el.dataset.bg = bgState[i].bg;
|
||||
el.dataset.int = bgState[i].int;
|
||||
el.dataset.layout = layoutState[i];
|
||||
el.dataset.cont = continuous;
|
||||
el.dataset.tagout = tagOut;
|
||||
el.dataset.frame = frameStyle;
|
||||
el.dataset.editmode = editMode;
|
||||
el.style.setProperty("--slide-i", i);
|
||||
el.innerHTML = BG_HTML;
|
||||
buildWaben(el.querySelector(".layer-waben"), i);
|
||||
|
||||
/* Jede Slide traegt das vollstaendige Blatt, nicht nur ihre Nachbarn.
|
||||
Vorher waren es i-1 bis i+1, und ein Element liess sich damit genau eine
|
||||
@@ -1997,7 +1919,6 @@
|
||||
el.dataset.bg = bgState[i].bg;
|
||||
el.dataset.int = bgState[i].int;
|
||||
el.dataset.layout = layoutState[i];
|
||||
el.dataset.cont = continuous;
|
||||
el.dataset.tagout = tagOut;
|
||||
el.dataset.frame = frameStyle;
|
||||
if (SLIDES[i].type === "title") rebuildPage(i);
|
||||
@@ -2023,7 +1944,6 @@
|
||||
|
||||
// Reflect the active slide's own ground in the panel.
|
||||
function syncBgButtons() {
|
||||
press("bgs", "b", bgState[current].bg);
|
||||
press("ints", "i", bgState[current].int);
|
||||
}
|
||||
|
||||
@@ -3352,6 +3272,79 @@
|
||||
}
|
||||
});
|
||||
|
||||
/* ─── Menueleiste ────────────────────────────────────────────────────────
|
||||
Die Eintraege fuehren nichts selbst aus, sondern betaetigen die Schalter
|
||||
im Bedienfeld. Damit gibt es weiter genau eine Stelle, an der ein
|
||||
Verhalten steht, und die Leiste kann nicht auseinanderlaufen.
|
||||
data-klick Knopf mit dieser id anklicken
|
||||
data-opt Knopf einer Optionsgruppe: gruppe:attribut:wert
|
||||
data-tun benannte Aktion
|
||||
data-gehe anderes Projekt oeffnen */
|
||||
(function menueleiste() {
|
||||
const bar = document.getElementById("menubar");
|
||||
if (!bar) return;
|
||||
const menues = [...bar.querySelectorAll(".menu")];
|
||||
const zu = () => menues.forEach(m => delete m.dataset.offen);
|
||||
|
||||
const AKTION = { undo, redo };
|
||||
|
||||
// Haken und graue Eintraege erst beim Oeffnen setzen: vorher weiss die
|
||||
// Leiste nicht, was gerade gilt.
|
||||
function stand(m) {
|
||||
m.querySelectorAll("button[data-opt]").forEach(b => {
|
||||
const [gruppe, attr, wert] = b.dataset.opt.split(":");
|
||||
const q = document.querySelector("#" + gruppe + " button[data-" + attr + '="' + wert + '"]');
|
||||
const an = q && q.getAttribute("aria-pressed") === "true";
|
||||
b.querySelector(".haken")?.remove();
|
||||
b.insertAdjacentHTML("afterbegin",
|
||||
'<span class="haken">' + (an ? "✓" : "") + "</span>");
|
||||
});
|
||||
m.querySelectorAll("button[data-klick]").forEach(b => {
|
||||
const q = document.getElementById(b.dataset.klick);
|
||||
b.disabled = !q || q.disabled;
|
||||
});
|
||||
m.querySelectorAll("button[data-gehe]").forEach(b => {
|
||||
const hier = b.dataset.gehe.endsWith(location.pathname.split("/").pop() || "post1.html");
|
||||
b.querySelector(".haken")?.remove();
|
||||
b.insertAdjacentHTML("afterbegin",
|
||||
'<span class="haken">' + (hier ? "✓" : "") + "</span>");
|
||||
});
|
||||
}
|
||||
|
||||
bar.addEventListener("click", e => {
|
||||
const titel = e.target.closest(".menu > button");
|
||||
if (titel) {
|
||||
const m = titel.parentElement;
|
||||
const war = m.dataset.offen === "ja";
|
||||
zu();
|
||||
if (!war) { m.dataset.offen = "ja"; stand(m); }
|
||||
return;
|
||||
}
|
||||
const el = e.target.closest(".liste button");
|
||||
if (!el || el.disabled) return;
|
||||
zu();
|
||||
if (el.dataset.gehe) { location.href = el.dataset.gehe; return; }
|
||||
if (el.dataset.tun) { (AKTION[el.dataset.tun] || (() => {}))(); return; }
|
||||
if (el.dataset.klick) { document.getElementById(el.dataset.klick)?.click(); return; }
|
||||
if (el.dataset.opt) {
|
||||
const [gruppe, attr, wert] = el.dataset.opt.split(":");
|
||||
document.querySelector("#" + gruppe + " button[data-" + attr + '="' + wert + '"]')?.click();
|
||||
}
|
||||
});
|
||||
|
||||
// Ueberfahren wechselt das offene Menue, wie gewohnt.
|
||||
bar.addEventListener("mouseover", e => {
|
||||
const titel = e.target.closest(".menu > button");
|
||||
if (!titel || !menues.some(m => m.dataset.offen === "ja")) return;
|
||||
const m = titel.parentElement;
|
||||
if (m.dataset.offen === "ja") return;
|
||||
zu(); m.dataset.offen = "ja"; stand(m);
|
||||
});
|
||||
|
||||
document.addEventListener("mousedown", e => { if (!bar.contains(e.target)) zu(); });
|
||||
document.addEventListener("keydown", e => { if (e.key === "Escape") zu(); });
|
||||
})();
|
||||
|
||||
document.getElementById("reset-all").addEventListener("click", resetAll);
|
||||
|
||||
// Übersicht der Standards, direkt aus derselben Tabelle wie der Reset.
|
||||
@@ -3478,14 +3471,6 @@
|
||||
const b = e.target.closest("button");
|
||||
if (b) { layoutState[current] = b.dataset.l; syncLayoutButtons(); rebuildPage(current); applyAll(); saveState(); }
|
||||
});
|
||||
document.getElementById("conts").addEventListener("click", e => {
|
||||
const b = e.target.closest("button");
|
||||
if (b) { continuous = b.dataset.c; press("conts", "c", continuous); applyAll(); saveState(); }
|
||||
});
|
||||
document.getElementById("bgs").addEventListener("click", e => {
|
||||
const b = e.target.closest("button");
|
||||
if (b) { bgState[current].bg = b.dataset.b; syncBgButtons(); applyAll(); saveState(); }
|
||||
});
|
||||
document.getElementById("ints").addEventListener("click", e => {
|
||||
const b = e.target.closest("button");
|
||||
if (b) { bgState[current].int = b.dataset.i; syncBgButtons(); applyAll(); saveState(); }
|
||||
@@ -3511,7 +3496,6 @@
|
||||
document.getElementById("dl-png").addEventListener("click", guard(downloadOne));
|
||||
document.getElementById("dl-all").addEventListener("click", guard(downloadAll));
|
||||
|
||||
const BG_CYCLE = ["formen", "formen-g", "nur-g", "waben", "punkte", "raster", "aus"];
|
||||
/* ⌘/Strg + Z. Eigener Zuhoerer, weil der allgemeine unten alles mit
|
||||
Sondertaste durchlaesst. In Eingabefeldern hat das Zurueckgehen des
|
||||
Browsers Vorrang, sonst kaeme man aus einem Tippfehler nicht mehr heraus. */
|
||||
@@ -3551,11 +3535,6 @@
|
||||
layoutState[current] = cat[(n + 1) % cat.length].id;
|
||||
syncLayoutButtons(); rebuildPage(current); applyAll(); saveState();
|
||||
}
|
||||
else if (k === "m") {
|
||||
const st = bgState[current];
|
||||
st.bg = BG_CYCLE[(BG_CYCLE.indexOf(st.bg) + 1) % BG_CYCLE.length];
|
||||
syncBgButtons(); applyAll();
|
||||
}
|
||||
else if (k === "i") {
|
||||
const st = bgState[current];
|
||||
st.int = st.int === "dezent" ? "kraeftig" : "dezent";
|
||||
@@ -3573,7 +3552,6 @@
|
||||
press("frames", "f", frameStyle); applyAll(); saveState();
|
||||
}
|
||||
else if (k === "g") { tagOut = tagOut === "an" ? "aus" : "an"; press("tagouts", "o", tagOut); applyAll(); saveState(); }
|
||||
else if (k === "c") { continuous = continuous === "an" ? "aus" : "an"; press("conts", "c", continuous); applyAll(); saveState(); }
|
||||
else if (k === "d") guard(downloadOne)();
|
||||
else if (k === "a") guard(downloadAll)();
|
||||
});
|
||||
@@ -3608,7 +3586,6 @@
|
||||
press("variants", "v", variant);
|
||||
press("tilts", "t", tilt);
|
||||
press("quality", "q", String(superSample));
|
||||
press("conts", "c", continuous);
|
||||
press("tagouts", "o", tagOut);
|
||||
press("frames", "f", frameStyle);
|
||||
press("views", "w", view);
|
||||
|
||||
+3611
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user