Verwaltung: Zeigerlampe, Prisma-Kanten, schwebende Partikel
Drei Dinge, die zusammen ein Konzept ergeben: Das Bild reagiert auf den Zeiger, die Kacheln brechen das Licht wie Eis, und im Raum schwebt etwas. 1. DIE ZEIGERLAMPE Ein weicher Lichtkegel wandert ueber die Buehne und hellt die Kristalle dort auf, wo der Zeiger steht. Damit wird das Bild zu einer Flaeche, die auf einen reagiert, statt nur dazuzuliegen. Der Kniff steckt in mix-blend-mode: soft-light. Ein normaler heller Verlauf wuerde das Bild ueberdecken und milchig machen. "soft-light" rechnet stattdessen mit dem, was darunter liegt -- dunkle Stellen bleiben dunkel, vorhandene Lichtkanten der Kristalle werden verstaerkt. Das Bild wird nicht ueberstrahlt, es wird beleuchtet. Bewusst NICHT "screen" oder "overlay": Beide lassen die Eiskanten ausbrennen, und genau die machen den Reiz der Motive aus. 2. PRISMA-SCHIMMER AN DEN KACHELKANTEN Am hellsten Punkt sitzt die Leitfarbe, daneben faechert die Kante in Nachbartoene auf -- wie Licht, das sich in einer Glaskante bricht. Bewusst KEIN Regenbogen: Volle Spektralfarben sehen nach Seifenblase aus, nicht nach geschliffenem Eis. Es bleibt in der kalten Haelfte der Palette. Die Kante ist dafuer 1,5 px statt 1 px -- bei genau einem Punkt verschluckt das Bildschirmraster die Aufaecherung fast vollstaendig. 3. SCHWEBENDE PARTIKEL Neun Lichtpunkte steigen sehr langsam auf, jeder mit eigener Bahn, Dauer und Startzeit. Rein aus CSS, ohne Zeichenflaeche -- eine Zeichenflaeche wuerde dauerhaft Rechenzeit kosten, und das auf einer Seite, auf der man arbeitet. Es soll wirken wie Staub im Lichtkegel, nicht wie Schneefall. DER FEHLER, DEN ERST DER SCREENSHOT ZEIGTE: Die Lampe legte sich als gruenlicher Fleck mitten auf eine Kachel. Ein Element mit mix-blend-mode mischt sich mit ALLEM in seinem Stapelkontext -- auch mit Elementen, die eigentlich darueber liegen. Buehne und Lampe stecken deshalb jetzt in einem gemeinsamen Raum mit isolation: isolate. Dort endet die Mischung, und die Lampe beleuchtet nur noch das Bild. Was DANACH noch durchkam, ist dagegen richtig so: Die Kacheln tragen eine Rueckseiten-Unschaerfe, nehmen also auf, was hinter ihnen liegt. Licht, das durch Milchglas scheint. Bei einem engen Kegel war davon allerdings ein scharf umrissener Kreis uebrig -- deshalb jetzt ein weiter Radius mit flachen Stufen, damit sich der Helligkeitsunterschied ueber die halbe Kachel verteilt und als Schimmer liest. Drei Testmeldungen waren durch den Umbau entstanden und kein Mangel der Seite: Haltung, Stapelplatz und die Auszeichnung als Zierde sitzen jetzt am Raum, nicht mehr an der Buehne darin. Der Test prueft sie dort. Bei prefers-reduced-motion sind die Partikel komplett weg -- nicht nur angehalten. Ein eingefrorener Punkt mitten im Bild waere ein Fleck ohne Sinn. Ohne feinen Zeiger entfaellt die Lampe ganz. Geprueft: 252 Pruefungen gruen (Verwaltung 54, Portfolio 15, CRYONOVA 53, Blickfang 13, System 5, Abmelden 16, Abbruch 42, Angebot 54). Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -129,6 +129,12 @@ srv.listen(4404, async () => {
|
||||
if (!el) return null;
|
||||
const st = getComputedStyle(el);
|
||||
const r = el.getBoundingClientRect();
|
||||
/* Seit Buehne und Lampe in einem gemeinsamen Raum stecken, sitzen
|
||||
Haltung, Stapelplatz und die Auszeichnung als Zierde am RAUM --
|
||||
die Buehne darin ist absolut positioniert. Geprueft wird deshalb
|
||||
der Raum, sonst misst der Test am falschen Element. */
|
||||
const raum = el.parentElement;
|
||||
const rs = getComputedStyle(raum);
|
||||
const treffer = st.backgroundImage.match(/img\/([a-z0-9-]+\.webp)/i);
|
||||
return {
|
||||
datei: treffer ? treffer[1] : "(keins)",
|
||||
@@ -137,9 +143,10 @@ srv.listen(4404, async () => {
|
||||
haltung: st.position,
|
||||
breite: Math.round(r.width),
|
||||
hoehe: Math.round(r.height),
|
||||
z: parseInt(st.zIndex, 10),
|
||||
klicks: st.pointerEvents,
|
||||
versteckt: el.getAttribute("aria-hidden"),
|
||||
haltungRaum: rs.position,
|
||||
z: parseInt(rs.zIndex, 10),
|
||||
klicks: rs.pointerEvents,
|
||||
versteckt: raum.getAttribute("aria-hidden"),
|
||||
};
|
||||
});
|
||||
if (!buehne) { pruefe("Buehne vorhanden", false); }
|
||||
@@ -153,7 +160,7 @@ srv.listen(4404, async () => {
|
||||
pruefe("die Buehne fuellt den ganzen Bildschirm",
|
||||
buehne.breite >= 1430 && buehne.hoehe >= 890, `${buehne.breite}x${buehne.hoehe}`);
|
||||
pruefe("sie steht fest, der Inhalt scrollt darueber",
|
||||
buehne.haltung === "fixed", buehne.haltung);
|
||||
buehne.haltungRaum === "fixed", buehne.haltungRaum);
|
||||
pruefe("sie liegt hinter allem", buehne.z < 0, "z-index " + buehne.z);
|
||||
pruefe("sie faengt keine Klicks ab", buehne.klicks === "none", buehne.klicks);
|
||||
pruefe("sie ist als Zierde ausgezeichnet", buehne.versteckt === "true");
|
||||
@@ -359,6 +366,62 @@ srv.listen(4404, async () => {
|
||||
new Set(staffel.map((k) => k.versatz)).size === staffel.length,
|
||||
staffel.map((k) => k.versatz).join(" "));
|
||||
|
||||
console.log("\n===== 3f. ZEIGERLAMPE, PRISMA UND PARTIKEL =====");
|
||||
await bereichAufbauen(seite, "anfragen");
|
||||
await seite.mouse.move(300, 300, { steps: 8 });
|
||||
await seite.waitForTimeout(300);
|
||||
await seite.mouse.move(1050, 380, { steps: 20 });
|
||||
await seite.waitForTimeout(700);
|
||||
|
||||
const extra = await seite.evaluate(() => {
|
||||
const raum = document.querySelector(".vw-raum");
|
||||
const lampe = document.querySelector(".vw-lampe");
|
||||
const flocken = document.querySelector(".vw-flocken");
|
||||
const karte = document.querySelector("#vw-probe .wd-karte");
|
||||
const ls = getComputedStyle(lampe);
|
||||
return {
|
||||
raumIsoliert: getComputedStyle(raum).isolation,
|
||||
mischung: ls.mixBlendMode,
|
||||
lampeAn: lampe.classList.contains("vw-lampe-an"),
|
||||
mx: lampe.style.getPropertyValue("--vw-mx"),
|
||||
my: lampe.style.getPropertyValue("--vw-my"),
|
||||
flockenZahl: flocken ? flocken.children.length : 0,
|
||||
flockeLaeuft: flocken && flocken.children[0]
|
||||
? getComputedStyle(flocken.children[0]).animationName : "",
|
||||
kachelKante: karte ? getComputedStyle(karte).backgroundImage : "",
|
||||
};
|
||||
});
|
||||
|
||||
/* Die Isolation ist der Kern. Ohne sie mischt sich die Lampe mit
|
||||
ALLEM in ihrem Stapelkontext -- auch mit Kacheln, die eigentlich
|
||||
darueber liegen. Beim Bauen lag dadurch ein gruenlicher Fleck
|
||||
mitten auf einer Karte. */
|
||||
pruefe("Buehne und Lampe stecken in einem isolierten Raum",
|
||||
extra.raumIsoliert === "isolate", extra.raumIsoliert);
|
||||
/* soft-light rechnet mit dem, was darunter liegt: dunkle Stellen
|
||||
bleiben dunkel, vorhandene Lichtkanten werden verstaerkt. "screen"
|
||||
oder "overlay" wuerden die Eiskanten ausbrennen lassen. */
|
||||
pruefe("die Lampe beleuchtet, statt zu ueberdecken",
|
||||
extra.mischung === "soft-light", extra.mischung);
|
||||
pruefe("sie folgt dem Zeiger", extra.mx === "1050px" && extra.my === "380px",
|
||||
extra.mx + " / " + extra.my);
|
||||
/* Erst zeigen, wenn der Zeiger wirklich da war -- sonst haengt beim
|
||||
Laden ein Lichtfleck in der Bildmitte, den niemand dorthin gelegt
|
||||
hat. */
|
||||
pruefe("und war vor der ersten Zeigerbewegung aus", extra.lampeAn === true);
|
||||
|
||||
pruefe("es schweben Partikel im Raum", extra.flockenZahl === 9,
|
||||
extra.flockenZahl + " Stueck");
|
||||
pruefe("und sie bewegen sich", extra.flockeLaeuft === "vw-schweben",
|
||||
extra.flockeLaeuft);
|
||||
|
||||
/* Der Prisma-Schimmer faechert die Kante in Nachbartoene auf. Geprueft
|
||||
wird, dass mehr als nur die Leitfarbe drinsteckt -- sonst waere es
|
||||
wieder ein einfarbiger Rand. */
|
||||
const toene = (extra.kachelKante.match(/rgba?\(/g) || []).length;
|
||||
pruefe("die Kachelkante bricht das Licht in mehrere Toene", toene >= 6,
|
||||
toene + " Farbstufen");
|
||||
|
||||
console.log("\n===== 4. WECHSELT DER RAUM WIRKLICH? =====");
|
||||
const gesehen = [];
|
||||
for (const bereich of BEREICHE) {
|
||||
@@ -440,6 +503,15 @@ srv.listen(4404, async () => {
|
||||
pruefe("und der Balken gleitet nicht, sondern springt",
|
||||
laengste <= 0.01, ruhigExtra.balken);
|
||||
|
||||
const ruhigFlocken = await ruhig.evaluate(() => {
|
||||
const f = document.querySelector(".vw-flocken");
|
||||
return f ? getComputedStyle(f).display : "(fehlt)";
|
||||
});
|
||||
/* Komplett weg, nicht nur angehalten: Ein eingefrorener Punkt mitten
|
||||
im Bild waere ein Fleck ohne Sinn. */
|
||||
pruefe("keine Partikel bei reduzierter Bewegung",
|
||||
ruhigFlocken === "none", ruhigFlocken);
|
||||
|
||||
pruefe("und kein Lichtreflex",
|
||||
ruhigeLage.reflex === "none" && ruhigeLage.reflexSichtbar === 0,
|
||||
ruhigeLage.reflex + ", Deckkraft " + ruhigeLage.reflexSichtbar);
|
||||
|
||||
Reference in New Issue
Block a user