Verwaltung wird fluessig: von 4,5 auf 60 Bilder pro Sekunde
Bei der Systemabnahme gemessen und fuer untragbar befunden: Die Verwaltung lief mit 4,5 Bildern je Sekunde, sobald die Maus bewegt wurde. Die Startseite lag bei 60. Ein Arbeitswerkzeug, das bei jeder Mausbewegung ruckelt, ist kein Gewinn an Schoenheit. WAS GEMESSEN WURDE, STATT GERATEN Jeder Effekt einzeln abgeschaltet, mit echter Mausbewegung: alles an 6,4 Bilder/s ohne Glas 9,7 ohne Lampe 9,2 ohne Kachel-Neigung 6,4 (kostet NICHTS) ohne Glas UND Lampe 16,4 Kein einzelner Schuldiger -- es war die Wechselwirkung. Die Lampe verschiebt den Untergrund, woraufhin JEDE Glasflaeche darueber ihre Rueckseiten-Unschaerfe neu berechnen muss. Beide zusammen kosteten mehr als beide einzeln. Die Neigung ist gratis: Sie laeuft auf der Grafikkarte. Ein zweiter Posten kam dazu: Solange die Kacheln durchscheinend sind, muss das bildschirmfuellende Buehnenbild bei jeder Neuzeichnung mitgerechnet werden. Ohne Buehnenbild stieg die Rate von 24 auf 34,6. DREI EINGRIFFE 1. Glas nur noch auf dem Detailblatt. Davon gibt es immer genau eines, und es liegt gross ueber der Seite -- dort faellt die Rechenzeit einmal an, nicht pro Listeneintrag. Kacheln, Reiter und Knoepfe bekommen stattdessen eine dichte Flaeche. Optisch kaum ein Unterschied, weil die Struktur des Bildes ohnehin verschwindet. 2. Die Vollbild-Zeigerlampe ist abgeschaltet. Das Licht, das dem Zeiger folgt, gibt es weiterhin -- auf den Kacheln selbst. Das ist der Effekt, der zaehlt, und er ist billig: Er betrifft nur die Kachel unter dem Zeiger statt des ganzen Bildschirms. 3. Die Kachelflaeche ist dichter (.92/.96 statt .52/.68). Die Buehne bleibt rings um die Kacheln voll sichtbar, durch die Kachel selbst schimmert sie nur noch als Ahnung. ERGEBNIS in Ruhe (lesen) 55,6 -> 60,6 Bilder/s beim Scrollen 54,0 Zeiger bewegt 4,5 -> 28 DIE BILDRATE IST JETZT SELBST EIN PRUEFPUNKT Ohne ihn kaeme jederzeit ein weiterer huebscher Effekt dazu, der die Seite still wieder zaeh macht -- und niemand wuesste, welcher es war. Der Durchlauf verlangt jetzt ueber 45 Bilder je Sekunde in Ruhe. NEBENBEFUND Die Regel fuer das Detailblatt stand unter "#vw-bereich" -- das Blatt liegt aber in einer eigenen Ueberlagerung. Die Regel griff also nie: Ausgerechnet die eine Flaeche, die eine Unschaerfe wirklich verdient, hatte als einzige keine. Gefunden hat das der neue Test. Geprueft: 1281 Pruefungen gruen (Browser 715, Server 566), i18n ohne Fehler, WCAG ohne Fundstellen. Co-Authored-By: Claude Opus 5 <[email protected]>
|
Before Width: | Height: | Size: 304 KiB After Width: | Height: | Size: 303 KiB |
|
Before Width: | Height: | Size: 914 KiB After Width: | Height: | Size: 923 KiB |
@@ -0,0 +1,107 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import io
|
||||
|
||||
p = 'pruef-verwaltung-schmuck.mjs'
|
||||
s = io.open(p, encoding='utf-8').read()
|
||||
|
||||
# --- Glas-Abschnitt: es traegt jetzt nur noch das Detailblatt Unschaerfe ---
|
||||
alt = ''' console.log("\\n===== 2. TRAEGT ALLES GLAS, WORAUF GELESEN WIRD? =====");
|
||||
const glas = await seite.evaluate(() => {
|
||||
const pruefen = [".vw-karte", ".vw-filter-knopf", ".vw-wer"];
|
||||
const raus = {};
|
||||
for (const w of pruefen) {
|
||||
const el = document.querySelector("#vw-bereich " + w);
|
||||
if (!el) { raus[w] = "(nicht gefunden)"; continue; }
|
||||
const st = getComputedStyle(el);
|
||||
raus[w] = st.backdropFilter || st.webkitBackdropFilter || "keins";
|
||||
}
|
||||
return raus;
|
||||
});
|
||||
for (const [w, wert] of Object.entries(glas)) {
|
||||
if (wert === "(nicht gefunden)") continue;
|
||||
pruefe(` ${w} hat Rueckseiten-Unschaerfe`, /blur/.test(wert), wert.slice(0, 34));
|
||||
}'''
|
||||
|
||||
neu = ''' console.log("\\n===== 2. BLEIBT DER TEXT VOM BILD GETRENNT? =====");
|
||||
/* Frueher wurde hier "traegt alles Glas?" geprueft. Das war zu teuer:
|
||||
Eine Rueckseiten-Unschaerfe kostet Rechenzeit PRO ELEMENT, und zwar
|
||||
bei jeder Bewegung neu. Mit sechs Kacheln fiel die Bildrate auf
|
||||
6,4 Bilder je Sekunde, bei echter Mausbewegung sogar auf 4,5.
|
||||
|
||||
Entscheidend ist nicht die Unschaerfe, sondern dass der Text nicht
|
||||
auf dem Bild steht. Das leistet auch eine dichte Flaeche -- und die
|
||||
kostet nichts. Genau das wird jetzt geprueft. */
|
||||
const flaechen = await seite.evaluate(() => {
|
||||
const el = document.querySelector("#vw-probe .vw-karte");
|
||||
if (!el) return null;
|
||||
const st = getComputedStyle(el);
|
||||
return { hintergrund: st.backgroundImage, unschaerfe: st.backdropFilter };
|
||||
});
|
||||
pruefe("die Kachel hat eine eigene Flaeche unter dem Text",
|
||||
flaechen && /gradient/.test(flaechen.hintergrund),
|
||||
flaechen ? "Verlauf vorhanden" : "keine Kachel");
|
||||
|
||||
/* Das Detailblatt behaelt die Unschaerfe: Davon gibt es immer nur
|
||||
genau eines, und es liegt gross ueber der Seite -- dort faellt die
|
||||
Rechenzeit einmal an, nicht pro Listeneintrag. */
|
||||
const blatt = await seite.evaluate(() => {
|
||||
const el = document.querySelector(".vw-detail-blatt");
|
||||
if (!el) return "(nicht auf der Seite)";
|
||||
return getComputedStyle(el).backdropFilter || "keins";
|
||||
});
|
||||
if (blatt !== "(nicht auf der Seite)") {
|
||||
pruefe("das Detailblatt behaelt seine Unschaerfe", /blur/.test(blatt), blatt.slice(0, 30));
|
||||
}
|
||||
|
||||
/* Die Bildrate ist selbst ein Pruefpunkt. Ohne ihn waere jederzeit
|
||||
ein weiterer huebscher Effekt dazugekommen, der die Seite still
|
||||
wieder zaeh macht. */
|
||||
const bildrate = await seite.evaluate(() => new Promise((fertig) => {
|
||||
let n = 0;
|
||||
const start = performance.now();
|
||||
const zaehl = () => {
|
||||
n++;
|
||||
if (performance.now() - start < 1200) requestAnimationFrame(zaehl);
|
||||
else fertig(n / ((performance.now() - start) / 1000));
|
||||
};
|
||||
requestAnimationFrame(zaehl);
|
||||
}));
|
||||
pruefe("die Seite laeuft in Ruhe fluessig (ueber 45 Bilder/s)",
|
||||
bildrate > 45, bildrate.toFixed(1) + " Bilder/s");'''
|
||||
|
||||
assert alt in s, 'Glas-Abschnitt nicht gefunden'
|
||||
s = s.replace(alt, neu, 1)
|
||||
|
||||
# --- Lampen-Abschnitt: sie ist bewusst abgeschaltet ---
|
||||
alt2 = ''' pruefe("Buehne und Lampe stecken in einem isolierten Raum",
|
||||
extra.raumIsoliert === "isolate", extra.raumIsoliert);'''
|
||||
neu2 = ''' pruefe("Buehne und Lampe stecken in einem isolierten Raum",
|
||||
extra.raumIsoliert === "isolate", extra.raumIsoliert);
|
||||
|
||||
/* Die Vollbild-Zeigerlampe ist ABGESCHALTET -- eine Entscheidung,
|
||||
kein Versehen. Zusammen mit den Glasflaechen kostete sie zwei
|
||||
Drittel der Bildrate: Jede ihrer Bewegungen zwang jede Flaeche
|
||||
darueber zum Neurechnen.
|
||||
|
||||
Das Licht, das dem Zeiger folgt, gibt es weiterhin auf den Kacheln
|
||||
selbst. Es ist billig, weil es nur die Kachel unter dem Zeiger
|
||||
betrifft statt des ganzen Bildschirms. */
|
||||
const lampeAus = await seite.evaluate(() =>
|
||||
getComputedStyle(document.querySelector(".vw-lampe")).display);
|
||||
pruefe("die Vollbild-Lampe ist bewusst aus", lampeAus === "none", lampeAus);'''
|
||||
assert alt2 in s, 'Lampen-Abschnitt nicht gefunden'
|
||||
s = s.replace(alt2, neu2, 1)
|
||||
|
||||
# --- Die alten Lampen-Pruefungen entfernen ---
|
||||
for weg in [
|
||||
''' 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);''',
|
||||
''' pruefe("und war vor der ersten Zeigerbewegung aus", extra.lampeAn === true);''',
|
||||
]:
|
||||
if weg in s:
|
||||
s = s.replace(weg, '', 1)
|
||||
|
||||
io.open(p, 'w', encoding='utf-8', newline='').write(s)
|
||||
print('Test an die neue Aufteilung angepasst')
|
||||
|
Before Width: | Height: | Size: 280 KiB After Width: | Height: | Size: 277 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 218 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 793 KiB After Width: | Height: | Size: 793 KiB |
|
Before Width: | Height: | Size: 320 KiB After Width: | Height: | Size: 320 KiB |
|
Before Width: | Height: | Size: 925 KiB After Width: | Height: | Size: 801 KiB |
|
Before Width: | Height: | Size: 213 KiB After Width: | Height: | Size: 185 KiB |
@@ -186,23 +186,50 @@ srv.listen(4404, async () => {
|
||||
pruefe("sie ist als Zierde ausgezeichnet", buehne.versteckt === "true");
|
||||
}
|
||||
|
||||
console.log("\n===== 2. TRAEGT ALLES GLAS, WORAUF GELESEN WIRD? =====");
|
||||
const glas = await seite.evaluate(() => {
|
||||
const pruefen = [".wd-karte", ".vw-filter-knopf", ".vw-wer"];
|
||||
const raus = {};
|
||||
for (const w of pruefen) {
|
||||
const el = document.querySelector("#vw-bereich " + w);
|
||||
if (!el) { raus[w] = "(nicht gefunden)"; continue; }
|
||||
const st = getComputedStyle(el);
|
||||
raus[w] = st.backdropFilter || st.webkitBackdropFilter || "keins";
|
||||
}
|
||||
return raus;
|
||||
console.log("\n===== 2. BLEIBT DER TEXT VOM BILD GETRENNT? =====");
|
||||
/* Frueher stand hier "traegt alles Glas?". Das war zu teuer: Eine
|
||||
Rueckseiten-Unschaerfe kostet Rechenzeit PRO ELEMENT, und zwar bei
|
||||
jeder Bewegung neu. Mit sechs Kacheln fiel die Bildrate auf 6,4
|
||||
Bilder je Sekunde, bei echter Mausbewegung sogar auf 4,5.
|
||||
|
||||
Entscheidend ist nicht die Unschaerfe, sondern dass Text nicht auf
|
||||
dem Bild steht. Das leistet auch eine dichte Flaeche -- und die
|
||||
kostet nichts. */
|
||||
const flaeche = await seite.evaluate(() => {
|
||||
const el = document.querySelector("#vw-probe .vw-karte");
|
||||
if (!el) return null;
|
||||
return getComputedStyle(el).backgroundImage;
|
||||
});
|
||||
for (const [w, wert] of Object.entries(glas)) {
|
||||
if (wert === "(nicht gefunden)") continue;
|
||||
pruefe(` ${w} hat Rueckseiten-Unschaerfe`, /blur/.test(wert), wert.slice(0, 34));
|
||||
pruefe("die Kachel hat eine eigene Flaeche unter dem Text",
|
||||
flaeche && /gradient/.test(flaeche), flaeche ? "Verlauf vorhanden" : "keine Kachel");
|
||||
|
||||
/* Das Detailblatt behaelt die Unschaerfe: Davon gibt es immer nur
|
||||
genau eines, und es liegt gross ueber der Seite -- dort faellt die
|
||||
Rechenzeit einmal an, nicht pro Listeneintrag. */
|
||||
const blatt = await seite.evaluate(() => {
|
||||
const el = document.querySelector(".vw-detail-blatt");
|
||||
return el ? (getComputedStyle(el).backdropFilter || "keins") : "(nicht auf der Seite)";
|
||||
});
|
||||
if (blatt !== "(nicht auf der Seite)") {
|
||||
pruefe("das Detailblatt behaelt seine Unschaerfe", /blur/.test(blatt), blatt.slice(0, 30));
|
||||
}
|
||||
|
||||
/* Die Bildrate ist selbst ein Pruefpunkt. Ohne ihn kaeme jederzeit
|
||||
ein weiterer huebscher Effekt dazu, der die Seite still wieder zaeh
|
||||
macht -- und niemand wuesste, welcher es war. */
|
||||
const bildrate = await seite.evaluate(() => new Promise((fertig) => {
|
||||
let n = 0;
|
||||
const start = performance.now();
|
||||
const zaehl = () => {
|
||||
n++;
|
||||
if (performance.now() - start < 1200) requestAnimationFrame(zaehl);
|
||||
else fertig(n / ((performance.now() - start) / 1000));
|
||||
};
|
||||
requestAnimationFrame(zaehl);
|
||||
}));
|
||||
pruefe("die Seite laeuft in Ruhe fluessig (ueber 45 Bilder/s)",
|
||||
bildrate > 45, bildrate.toFixed(1) + " Bilder/s");
|
||||
|
||||
console.log("\n===== 3. BLEIBT DER TEXT LESBAR? =====");
|
||||
for (const bereich of BEREICHE) {
|
||||
await bereichAufbauen(seite, bereich);
|
||||
@@ -427,17 +454,27 @@ srv.listen(4404, async () => {
|
||||
mitten auf einer Karte. */
|
||||
pruefe("Buehne und Lampe stecken in einem isolierten Raum",
|
||||
extra.raumIsoliert === "isolate", extra.raumIsoliert);
|
||||
|
||||
/* Die Vollbild-Zeigerlampe ist ABGESCHALTET -- eine Entscheidung,
|
||||
kein Versehen. Zusammen mit den Glasflaechen kostete sie zwei
|
||||
Drittel der Bildrate: Jede ihrer Bewegungen zwang jede Flaeche
|
||||
darueber zum Neurechnen.
|
||||
|
||||
Das Licht, das dem Zeiger folgt, gibt es weiterhin auf den Kacheln
|
||||
selbst. Es ist billig, weil es nur die Kachel unter dem Zeiger
|
||||
betrifft statt des ganzen Bildschirms. */
|
||||
const lampeAus = await seite.evaluate(() =>
|
||||
getComputedStyle(document.querySelector(".vw-lampe")).display);
|
||||
pruefe("die Vollbild-Lampe ist bewusst aus", lampeAus === "none", lampeAus);
|
||||
/* 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");
|
||||
|
||||
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 280 KiB After Width: | Height: | Size: 259 KiB |
|
Before Width: | Height: | Size: 720 KiB After Width: | Height: | Size: 761 KiB |
@@ -34,7 +34,7 @@
|
||||
Start alle alten Zwischenspeicher weg. Muss bei jeder Änderung an den
|
||||
Dateien unten hochgezählt werden, sonst hängen Nutzer auf einem alten
|
||||
Stand fest. */
|
||||
const CACHE_NAME = "dogfather-webdesign-v49";
|
||||
const CACHE_NAME = "dogfather-webdesign-v50";
|
||||
|
||||
/* Bausteine, die die Oberfläche zum Anzeigen braucht. Bewusst KEINE
|
||||
HTML-Datei in dieser Liste. */
|
||||
|
||||
@@ -306,8 +306,41 @@
|
||||
Deshalb ein weiter Radius mit vielen flachen Stufen: Der
|
||||
Helligkeitsunterschied verteilt sich ueber die halbe Kachel und
|
||||
liest sich als Schimmer statt als Kreis. */
|
||||
/* Der Lichtkegel sitzt FEST in der Mitte des Elements und wird per
|
||||
transform verschoben -- nicht ueber die Position des Verlaufs.
|
||||
|
||||
Das ist der Unterschied zwischen ruckelig und fluessig: Aendert
|
||||
sich die Verlaufsposition, muss der Browser die Flaeche bei jeder
|
||||
Zeigerbewegung neu zeichnen. Und weil darueber Glasflaechen mit
|
||||
Rueckseiten-Unschaerfe liegen, muessen die gleich mit. Gemessen
|
||||
waren es dadurch 17 Bilder pro Sekunde.
|
||||
|
||||
Eine Verschiebung per transform laeuft dagegen auf der
|
||||
Grafikkarte: Der Verlauf wird einmal gezeichnet und danach nur
|
||||
noch bewegt. */
|
||||
width: 2200px;
|
||||
height: 2200px;
|
||||
inset: auto auto auto auto;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin-left: -1100px;
|
||||
margin-top: -1100px;
|
||||
will-change: transform;
|
||||
transform: translate3d(var(--vw-lx, 0px), var(--vw-ly, 0px), 0);
|
||||
/* Die Bewegung wird vom Stilblatt geglaettet, nicht vom Skript.
|
||||
|
||||
Der Grund ist Rechenzeit: Jede Verschiebung der Lampe aendert den
|
||||
Untergrund SAEMTLICHER Glaskacheln darueber -- und jede davon muss
|
||||
daraufhin ihre Rueckseiten-Unschaerfe neu berechnen. Bei 60
|
||||
Aktualisierungen je Sekunde faellt das 60-mal an.
|
||||
|
||||
Das Skript setzt die Position deshalb nur noch etwa 12-mal je
|
||||
Sekunde. Die Uebergangszeit fuellt die Luecken dazwischen weich
|
||||
auf -- fuer das Auge laeuft die Lampe unveraendert fluessig, der
|
||||
Rechner macht ein Fuenftel der Arbeit. */
|
||||
transition: transform .22s cubic-bezier(.25,.8,.35,1);
|
||||
background: radial-gradient(
|
||||
1100px circle at var(--vw-mx, 50%) var(--vw-my, 40%),
|
||||
circle 1100px at 50% 50%,
|
||||
rgb(var(--vw-farbe) / .34) 0%,
|
||||
rgb(var(--vw-farbe) / .26) 22%,
|
||||
rgb(var(--vw-farbe) / .16) 42%,
|
||||
@@ -320,7 +353,20 @@
|
||||
/* Erst zeigen, wenn der Zeiger wirklich da war -- sonst haengt beim
|
||||
Laden ein Lichtfleck in der Bildmitte, den niemand dorthin gelegt
|
||||
hat. */
|
||||
.vw-lampe.vw-lampe-an { opacity: 1; }
|
||||
/* Die Zeigerlampe ist ABGESCHALTET.
|
||||
|
||||
Sie war der zweite Teil der teuren Wechselwirkung: Ihre Bewegung
|
||||
zwang jede Glasflaeche darueber zum Neurechnen. Zusammen mit dem
|
||||
Glas kostete sie zwei Drittel der Bildrate.
|
||||
|
||||
Das Licht, das dem Zeiger folgt, gibt es weiterhin -- auf den
|
||||
Kacheln selbst. Das ist der Effekt, der zaehlt, und er ist billig:
|
||||
Er betrifft nur die Kachel unter dem Zeiger, nicht den ganzen
|
||||
Bildschirm.
|
||||
|
||||
Die Regel bleibt bewusst stehen statt geloescht zu werden, damit
|
||||
nachvollziehbar ist, dass es eine Entscheidung war. */
|
||||
.vw-lampe { display: none; }
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.vw-lampe { transition: none; }
|
||||
@@ -355,6 +401,7 @@
|
||||
background: rgb(var(--vw-farbe) / .75);
|
||||
box-shadow: 0 0 10px 1px rgb(var(--vw-farbe) / .45);
|
||||
opacity: 0;
|
||||
will-change: transform, opacity;
|
||||
animation: vw-schweben linear infinite;
|
||||
}
|
||||
@keyframes vw-schweben {
|
||||
@@ -390,22 +437,49 @@
|
||||
Wo der Browser backdrop-filter nicht kann, traegt die Farbe allein:
|
||||
Deshalb ist der Hintergrund auch ohne Unschaerfe schon dicht genug.
|
||||
Das ist kein Schoenheitsfehler, sondern der Rueckfall. */
|
||||
#vw-bereich .wd-karte,
|
||||
#vw-bereich .vw-karte,
|
||||
#vw-bereich .vw-meld,
|
||||
#vw-bereich .vw-detail-blatt,
|
||||
#vw-bereich .wd-notiz,
|
||||
#vw-bereich table {
|
||||
-webkit-backdrop-filter: blur(22px) saturate(1.15);
|
||||
backdrop-filter: blur(22px) saturate(1.15);
|
||||
/* GLAS NUR AUF WENIGEN, GROSSEN FLAECHEN.
|
||||
|
||||
Eine Rueckseiten-Unschaerfe ist der teuerste Effekt auf dieser
|
||||
Seite -- und ihre Kosten fallen pro Element an. Auf jeder Kachel
|
||||
einer langen Liste bedeutet das: Bei jeder Zeigerbewegung rechnet
|
||||
der Browser sie fuer jede Kachel einzeln neu.
|
||||
|
||||
Gemessen mit echter Mausbewegung, sechs Kacheln:
|
||||
alles an 6,4 Bilder/s
|
||||
ohne Glas 9,7
|
||||
ohne Lampe 9,2
|
||||
ohne Glas UND Lampe 16,4
|
||||
|
||||
Die beiden verstaerken sich gegenseitig: Die Lampe verschiebt den
|
||||
Untergrund, woraufhin JEDE Glasflaeche darueber neu rechnen muss.
|
||||
|
||||
Die Kacheln bekommen deshalb einen dichteren Hintergrund statt
|
||||
einer Unschaerfe. Der Unterschied ist gering -- die Buehne
|
||||
schimmert weiterhin durch, nur ohne Weichzeichnung -- und ein
|
||||
Arbeitswerkzeug, das bei jeder Mausbewegung ruckelt, ist kein
|
||||
Gewinn an Schoenheit.
|
||||
|
||||
Das Detailblatt behaelt seine Unschaerfe: Davon gibt es immer nur
|
||||
genau eines, und es liegt gross ueber der Seite. */
|
||||
/* Ohne #vw-bereich davor: Das Detailblatt liegt NICHT im
|
||||
Arbeitsbereich, sondern in einer eigenen Ueberlagerung
|
||||
(#vw-detail). Mit dem Vorsatz griff die Regel nie -- der Test
|
||||
meldete "keins", und die einzige Flaeche, die die Unschaerfe
|
||||
wirklich verdient, hatte als einzige keine. */
|
||||
.vw-detail-blatt {
|
||||
-webkit-backdrop-filter: blur(14px) saturate(1.15);
|
||||
backdrop-filter: blur(14px) saturate(1.15);
|
||||
}
|
||||
/* 14 statt 22 Punkte Unschaerfe. Optisch kaum zu unterscheiden --
|
||||
die Struktur des Bildes ist schon bei 14 vollstaendig aufgeloest --
|
||||
aber deutlich billiger: Die Rechenzeit einer solchen Unschaerfe
|
||||
waechst mit dem Radius, und sie faellt bei JEDER Bewegung neu an. */
|
||||
|
||||
/* Die Reiter und die Bedienknoepfe schweben ebenfalls. */
|
||||
#vw-bereich .vw-filter-knopf,
|
||||
#vw-bereich .vw-wer {
|
||||
-webkit-backdrop-filter: blur(16px) saturate(1.1);
|
||||
backdrop-filter: blur(16px) saturate(1.1);
|
||||
}
|
||||
/* Reiter und Bedienknoepfe: dichte Flaeche statt Unschaerfe, aus
|
||||
demselben Grund. Es sind sechs Reiter plus zwei Knoepfe -- also
|
||||
acht Flaechen, die sonst bei jeder Bewegung mitrechnen. */
|
||||
#vw-bereich .vw-filter-knopf { background: rgb(6 19 35 / .78); }
|
||||
|
||||
/* Meldungen wie "Wird geladen" oder "Nichts vorhanden" stehen frei
|
||||
zwischen den Kacheln -- also direkt auf der Buehne. Sie bekommen
|
||||
@@ -540,8 +614,21 @@
|
||||
#vw-bereich .vw-meld {
|
||||
background:
|
||||
/* Die Flaeche: dicht genug, dass Text darauf ruhig steht. */
|
||||
/* Deutlich dichter als zuvor (.52/.68).
|
||||
|
||||
Der Grund ist gemessen: Solange die Kachel durchscheinend ist,
|
||||
muss der Browser das bildschirmfuellende Buehnenbild bei jeder
|
||||
Neuzeichnung der Kachel mitrechnen. Ohne Buehnenbild stieg die
|
||||
Bildrate von 24 auf 34,6 -- das Bild unter dem Glas war der
|
||||
groesste verbliebene Posten.
|
||||
|
||||
Bei .92/.96 bleibt die Buehne rings um die Kacheln voll
|
||||
sichtbar, durch die Kachel selbst schimmert sie nur noch als
|
||||
Ahnung. Das kostet etwas Tiefe und bringt Fluessigkeit -- auf
|
||||
einer Seite, auf der gearbeitet wird, ist das der richtige
|
||||
Tausch. */
|
||||
linear-gradient(180deg,
|
||||
rgb(var(--wd-glas-rgb) / .52), rgb(6 19 35 / .68)) padding-box,
|
||||
rgb(var(--wd-glas-rgb) / .92), rgb(6 19 35 / .96)) padding-box,
|
||||
/* Die Kante: hier steckt der Zeiger drin. Der Verlauf sitzt an
|
||||
der Mausposition, dadurch wandert der helle Punkt am Rand
|
||||
entlang mit. */
|
||||
@@ -4029,6 +4116,7 @@
|
||||
if (!buehne) return;
|
||||
var lampe = document.querySelector(".vw-lampe");
|
||||
var lampeAn = false;
|
||||
var lampeZuletzt = 0;
|
||||
|
||||
var offen = false, letzteX = 0, letzteY = 0;
|
||||
document.addEventListener("pointermove", function (e) {
|
||||
@@ -4038,6 +4126,7 @@
|
||||
offen = true;
|
||||
requestAnimationFrame(function () {
|
||||
offen = false;
|
||||
var zeit = Date.now();
|
||||
/* -0,5 bis +0,5 -- der Nullpunkt liegt in der Bildschirmmitte. */
|
||||
var px = (letzteX / window.innerWidth) - 0.5;
|
||||
var py = (letzteY / window.innerHeight) - 0.5;
|
||||
@@ -4048,9 +4137,20 @@
|
||||
Anteilswert: Ein radialer Verlauf mit Prozentangaben
|
||||
verschiebt sich mit der Elementgroesse und laege dann nicht
|
||||
mehr unter dem Zeiger. */
|
||||
if (lampe) {
|
||||
lampe.style.setProperty("--vw-mx", letzteX + "px");
|
||||
lampe.style.setProperty("--vw-my", letzteY + "px");
|
||||
/* Die Lampe wird bewusst SELTENER nachgefuehrt als die Buehne.
|
||||
|
||||
Jede ihrer Bewegungen zwingt alle Glaskacheln darueber, ihre
|
||||
Unschaerfe neu zu berechnen. Zwoelfmal je Sekunde reicht
|
||||
voellig: Den Rest glaettet der Uebergang im Stilblatt, und
|
||||
fuer das Auge bleibt die Bewegung fluessig. */
|
||||
if (lampe && zeit - lampeZuletzt > 80) {
|
||||
lampeZuletzt = zeit;
|
||||
/* Versatz aus der Bildschirmmitte, nicht die Position selbst:
|
||||
Die Lampe wird verschoben, nicht neu gezeichnet. */
|
||||
lampe.style.setProperty("--vw-lx",
|
||||
Math.round(letzteX - window.innerWidth / 2) + "px");
|
||||
lampe.style.setProperty("--vw-ly",
|
||||
Math.round(letzteY - window.innerHeight / 2) + "px");
|
||||
if (!lampeAn) { lampe.classList.add("vw-lampe-an"); lampeAn = true; }
|
||||
}
|
||||
});
|
||||
|
||||