Uebersicht: kein Zoom mehr, nur noch scrollen

Zwei Zoom-Ebenen lagen uebereinander, und beide waren falsch. Aussen ein
Rad-Zoom, der nur die iframes skaliert hat -- Beschriftung, Abstaende und
Polster stehen ausserhalb der Transformation und blieben stehen, also
standen beim Herauszoomen riesige Ueberschriften ueber winzigen Streifen.
Und innen reagierte die Post-Seite im iframe weiter auf ihr eigenes
Mausrad, weil sie ihren Canvas mitbringt.

Jetzt: jeder Streifen wird auf die Fensterbreite eingepasst, gescrollt
wird nur hoch und runter. Die iframes bekommen pointer-events: none --
die Uebersicht ist zum Ansehen da, bedient wird im Projekt selbst.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
dejanandClaude Opus 5 committed 2026-08-13 22:08:39 +02:00
1 parent 16b85a285a
commit 79821775b0
2 files changed
+24 -80

No files matched your search

+2 -1
View File
@@ -30,7 +30,8 @@ nach: jedes Projekt kommt als `iframe` mit `?nur=streifen`, und in diesem Modus
blendet die Post-Seite ihre Bedienoberfläche aus, zeigt den Streifen in
natürlicher Größe und **speichert nichts** — drei Kacheln, die beim Schließen
ihren Stand zurückschreiben, wären genau die Falle aus [`POST-2.md`](./POST-2.md) §6.
Skaliert wird außen; ziehen schiebt, das Rad zoomt, `Fit` passt ein.
Jeder Streifen ist auf die Fensterbreite eingepasst, gescrollt wird nur
hoch und runter — kein Zoom, weder außen noch im Streifen.
**Post 2 gibt es zweimal, in zwei Themes.** Projekt und Theme sind zwei
verschiedene Dinge: das Projekt sagt, welcher Beitrag, das Theme, wie er
+22 -79
View File
@@ -50,14 +50,17 @@
.menu .liste button:hover { background: #262A34; color: #FFFFFF; }
.menu .liste hr { border: 0; border-top: 1px solid #2E313B; margin: 5px 2px; }
/* Dieselbe Fläche wie im Generator: gepunkteter Grund, ziehbar, Rad zoomt. */
/* Derselbe gepunktete Grund wie im Generator, aber ohne dessen Canvas:
hier wird nur gescrollt. */
.stage { position: absolute; inset: 34px 0 0; overflow: hidden;
background-color: #101116;
background-image: radial-gradient(circle, #282B35 1.6px, transparent 1.6px);
background-size: 26px 26px;
}
.scroller { position: absolute; inset: 0; overflow: auto; overscroll-behavior: contain; }
.scroller.panning { cursor: grabbing; }
/* Nur hoch und runter. Die Streifen sind auf die Breite eingepasst,
also gibt es waagerecht nichts zu holen. */
.scroller { position: absolute; inset: 0; overflow-y: auto; overflow-x: hidden;
overscroll-behavior: contain; }
.flaeche {
width: max-content; min-width: 100%; height: max-content; min-height: 100%;
padding: 54px; display: flex; flex-direction: column; gap: 46px;
@@ -74,8 +77,12 @@
bleibt in Originalgröße und wird nur transformiert. Ohne den Rahmen
würde das ungeskalierte iframe die Fläche aufblähen. */
.rahmen { overflow: hidden; background: #FFFFFF; border: 1px solid #2E313B; }
/* pointer-events: none -- sonst zoomt das Mausrad im Streifen die
Post-Seite darin, die ja ihren eigenen Canvas mitbringt. Die Uebersicht
ist zum Ansehen da, bedient wird im Projekt selbst. */
.rahmen iframe {
display: block; border: 0; transform-origin: 0 0; background: #FFFFFF;
pointer-events: none;
}
.reihe.fehlt .rahmen { display: grid; place-items: center; width: 420px; height: 90px;
background: #16181F; color: #6E7480; font-size: 13px; }
@@ -87,13 +94,6 @@
border-top: 1px solid #23262F;
}
.hud p { margin: 0; font-size: 12px; color: #6E7480; letter-spacing: .04em; }
.zoom { margin-left: auto; display: flex; gap: 4px; }
.zoom button {
font: inherit; font-size: 13px; font-weight: 700; cursor: pointer;
background: #1D1F26; color: #C7CCD6; border: 1px solid #2E313B;
border-radius: 7px; padding: 6px 10px; min-width: 32px;
}
.zoom button:hover { background: #262A34; color: #FFFFFF; }
</style>
</head>
<body>
@@ -118,11 +118,6 @@
</div>
<div class="hud">
<p id="meta">Lade Streifen ...</p>
<div class="zoom">
<button id="zoom-out" title="Auszoomen">−</button>
<button id="zoom-fit" title="Einpassen">Fit</button>
<button id="zoom-in" title="Einzoomen">+</button>
</div>
</div>
</main>
@@ -140,10 +135,12 @@
const scroller = document.getElementById("scroller");
const meta = document.getElementById("meta");
/* Ein Streifen ist bis zu 6480 px breit. Der Maßstab ist deshalb nicht
frei, sondern immer relativ zu "passt in die Fläche" -- sonst müsste man
bei jedem Öffnen erst herauszoomen. zoom === null heißt eingepasst. */
let zoom = null;
/* Kein Zoom. Ein Streifen ist bis zu 6480 px breit und wird immer auf die
Fensterbreite eingepasst; gescrollt wird nur hoch und runter. Ein
Zwischenstand hatte Rad-Zoom und Zoomknöpfe -- das war doppelt gemoppelt,
weil die Post-Seite im iframe ihren eigenen Canvas mitbringt, und die
Beschriftungen skalierten nicht mit, standen beim Herauszoomen also
riesig über winzigen Streifen. */
const reihen = [];
function bauen() {
@@ -178,22 +175,15 @@
legen();
});
/* Beschriftung, Abstände und Polster skalieren NICHT mit -- sie stehen
außerhalb des transformierten iframes. Ein einfaches
"verfügbar / Gesamthöhe" ließ die letzte Reihe deshalb unten
hinauslaufen. Die feste Höhe muss vorher abgezogen werden. */
const POLSTER = 54 * 2, LUECKE = 46, KOPFZEILE = 32;
// Eingepasst wird nur in die Breite, die Höhe ergibt sich und wird gescrollt.
const POLSTER = 54 * 2;
function passend() {
const n = reihen.length;
const breit = Math.max(...reihen.map(r => r.w), 1080);
const hoch = reihen.reduce((s, r) => s + r.h, 0);
const fest = POLSTER + (n - 1) * LUECKE + n * KOPFZEILE;
return Math.min((scroller.clientWidth - POLSTER) / breit,
Math.max(0.02, (scroller.clientHeight - fest) / hoch), 0.5);
return Math.min((scroller.clientWidth - POLSTER) / breit, 0.5);
}
function legen() {
const k = zoom || passend();
const k = passend();
reihen.forEach(r => {
r.ram.style.width = r.w + "px";
r.ram.style.height = r.h + "px";
@@ -201,57 +191,14 @@
r.rahmen.style.width = Math.round(r.w * k) + "px";
r.rahmen.style.height = Math.round(r.h * k) + "px";
});
document.getElementById("zoom-fit").textContent = zoom ? Math.round(k * 100) + " %" : "Fit";
const offen = reihen.filter(r => r.da).length;
meta.textContent = offen < reihen.length
? "Lade Streifen ... " + offen + " von " + reihen.length
: reihen.length + " Projekte · " + reihen.map(r => Math.round(r.w / 1080) + " Slides").join(" · ");
}
function zoomAuf(k, anker) {
const vor = zoom || passend();
const ax = anker ? anker.x : scroller.clientWidth / 2;
const ay = anker ? anker.y : scroller.clientHeight / 2;
const s0 = scroller.getBoundingClientRect();
const f0 = flaeche.getBoundingClientRect();
const u = (s0.left + ax - f0.left) / vor;
const v = (s0.top + ay - f0.top) / vor;
zoom = Math.min(1, Math.max(0.02, k));
legen();
const f1 = flaeche.getBoundingClientRect();
scroller.scrollLeft += (f1.left + u * zoom) - (s0.left + ax);
scroller.scrollTop += (f1.top + v * zoom) - (s0.top + ay);
}
// ─── Bedienung: ziehen, Rad zoomt, Umschalt+Rad schiebt waagerecht ───────
let zieht = null;
scroller.addEventListener("pointerdown", e => {
if (e.button !== 0 && e.button !== 1) return;
zieht = { x: e.clientX, y: e.clientY, l: scroller.scrollLeft, t: scroller.scrollTop };
scroller.classList.add("panning");
scroller.setPointerCapture(e.pointerId);
});
scroller.addEventListener("pointermove", e => {
if (!zieht) return;
scroller.scrollLeft = zieht.l - (e.clientX - zieht.x);
scroller.scrollTop = zieht.t - (e.clientY - zieht.y);
});
const losen = () => { zieht = null; scroller.classList.remove("panning"); };
scroller.addEventListener("pointerup", losen);
scroller.addEventListener("pointercancel", losen);
scroller.addEventListener("wheel", e => {
if (e.shiftKey) return; // waagerecht schieben
e.preventDefault();
const r = scroller.getBoundingClientRect();
zoomAuf((zoom || passend()) * (e.deltaY < 0 ? 1.12 : 1 / 1.12),
{ x: e.clientX - r.left, y: e.clientY - r.top });
}, { passive: false });
document.getElementById("zoom-in").addEventListener("click", () => zoomAuf((zoom || passend()) * 1.2));
document.getElementById("zoom-out").addEventListener("click", () => zoomAuf((zoom || passend()) / 1.2));
document.getElementById("zoom-fit").addEventListener("click", () => { zoom = null; legen(); });
window.addEventListener("resize", () => { if (!zoom) legen(); });
// Kein Ziehen, kein Rad-Zoom: die Seite scrollt wie eine gewoehnliche Seite.
window.addEventListener("resize", legen);
// ─── Menü ────────────────────────────────────────────────────────────────
document.querySelectorAll(".menu").forEach(m => {
@@ -269,10 +216,6 @@
if (b.dataset.gehe) { location.href = b.dataset.gehe; return; }
if (b.dataset.klick === "neu") { bauen(); legen(); }
});
document.addEventListener("keydown", e => {
if (e.key === "0") { zoom = null; legen(); }
});
bauen();
legen();
})();