Die Bildschau und 2520 Farben statt 360
=== 1. BILDER OEFFNEN SICH MITTIG, MIT HUSKY UND HASE ===
Filipe: "wenn man bilder aufmacht, will ich dass die in der mitte sind.
beim hochformat soll links der husky sein und rechts der hase und beim
querformat soll oben dogfather und unten team dogi stehen da wo platz
ist ... ich will nicht dahin geschmissen sondern was richtig geiles mit
einem geilen hintergrund."
WAS VORHER PASSIERTE, und es war kein Fehler im Code: Der Klick fuehrte
auf die DATEI. Was man dann sah, war die eingebaute Bildanzeige des
Browsers -- schwarzer Grund, Bild oben links in der Ecke, auf seinem
Bildschirmfoto 1200 px Schwarz daneben. Eine Datei hat keine
Gestaltung. Wer Gestaltung will, muss eine SEITE zeigen.
Die Schau liegt jetzt UEBER dem Chat. Escape bringt einen dorthin
zurueck, wo man war, und das Gespraech laeuft im Hintergrund weiter --
ein zweiter Tab braeuchte eine eigene Seite, eine eigene Anmeldung und
einen eigenen Weg zurueck.
DER WEG IN DEN TAB BLEIBT TROTZDEM. Der Verweis hat unveraendert
`href`, `target` und `rel`; mittlere Maustaste, "In neuem Tab oeffnen"
und Herunterladen gehen wie seit jeher. Abgefangen wird nur der
gewoehnliche Klick -- und auch der nur, wenn die Schau geladen ist.
Wer Strg, Umschalt oder Befehl haelt, bekommt den alten Weg; das sind
die Griffe, die Leute seit zwanzig Jahren benutzen.
DIE BEGLEITER STEHEN DA, WO PLATZ IST -- und die Antwort darauf wird
GEMESSEN, nicht geschaetzt: nicht die Fensterbreite, sondern der Rest
neben dem Bild, nachdem es eingepasst ist. Eine Schwelle wie "ab
1100 px" waere fuer ein 3:4-Foto richtig und fuer ein 9:16-Foto auf
demselben Schirm falsch. Unter 170 px bleibt der Husky weg: Eine Figur,
die ein Streifen ist, steht besser nicht da.
Husky und Hase sind eigens verkleinert (2,1 MB und 1,0 MB werden 40 kB
und 32 kB) und bekommen weiche Raender -- ihr Hintergrund ist dunkel,
aber nicht durchsichtig; als Rechteck saehe man zwei Kaesten.
Der erste Anlauf spiegelte den Hasen, damit beide "nach innen" schauen
-- ein alter Reflex aus dem Plakatsatz. Auf dem Probebild stand danach
"Hasi Dog" seitenverkehrt auf seinem Hoodie. Schrift im Bild spiegelt
man nie.
pruef-chat-anhaenge bekommt 14 neue Punkte, darunter beide Formate und
zwei Gegenproben: Strg+Klick oeffnet die Schau NICHT (sonst hiesse "sie
geht auf" nur, dass der alte Weg verloren ist), und im Hochformat liegt
KEINE der Figuren ueber dem Foto.
NEBENBEFUND, den die Pruefung gefunden hat: Die Sprachnachricht war auf
165 px geschrumpft -- zu schmal fuer den Schieber. Ursache war keine
Aenderung an ihr, sondern eine Folge: Die Blase ist so breit wie ihr
breitester Inhalt, und seit die Handgriffe darunter Zeichen statt
Woerter sind (123 statt ueber 400 px), bestimmt das Abspielgeraet die
Breite selbst. Eine Reihe kuerzer zu machen hat einen Schieber schmaler
gemacht, drei Bildschirme weiter.
=== 2. DER FARBKREIS: HELLER UND DUNKLER ===
Filipe: "dieser kreis muss viel perfekter sein. ich will dass die leute
auch heller und dunkler aussuchen koennen ... so dass die leute viel
krassere moeglichkeiten haben."
WARUM DAS BIS HEUTE NICHT GING: Die 360 Toene liegen alle auf DERSELBEN
Leuchtdichte. Das war kein Zufall -- solange die Blase in der gewaehlten
Farbe stand, musste jede dieser Flaechen dieselbe Schrift tragen. Eine
hellere Farbe zuzulassen hiesse damals: irgendwo wird eine Nachricht
unlesbar.
SEIT DEM 25.09.2026 IST DIE BEDINGUNG EINE ANDERE. Die Blase ist fuer
alle dunkles Glas; der Ton ist Kante und NAME. Damit faellt die alte
Regel weg, und an ihre Stelle tritt: der Ton muss als Name auf dem
Blasengrund lesbar bleiben.
DIE ZAHLEN SIND GEMESSEN, NICHT GEWAEHLT. Ueber alle 360 Winkel, jeweils
der schlechteste Fall:
40 % schwarz 4,468 -- unter der Schwelle, faellt raus
34 % schwarz 4,555 -- ginge, aber ohne Reserve
30 % schwarz 4,619 <- die dunkelste Stufe
0 % 5,12 <- die Mitte, der alte Kreis
55 % weiss 9,6 <- die hellste Stufe
Sieben Stufen, 2520 Farben statt 360. pruef-chat-neu rechnet jede
einzelne nach -- die knappste hat 2,6 Prozent Reserve.
DIE ALTEN SCHLUESSEL BLEIBEN GUELTIG. "ton-214" heisst weiterhin genau
dieselbe Farbe; die Stufe steht als Zusatz dahinter ("ton-214-s6"). Wer
seit dem 23.09. eine Farbe traegt, traegt nach diesem Umbau dieselbe.
DIE PROBE IN DER MITTE ZEIGT ENDLICH, WAS MAN BEKOMMT. Dort stand eine
gefuellte Flaeche mit heller Schrift -- so sah die Blase bis heute frueh
aus. Jetzt steht dort derselbe Blasengrund und darauf der Ton als Name,
mit genau der Rechnung aus chat.css. Das ist nicht nur ehrlicher, es
macht die sieben Stufen erst moeglich: Eine gefuellte Flaeche muesste
Schrift tragen, und bei sehr hellen Toenen schafft das keine der beiden
Schriftfarben mehr (4,1 statt noetiger 7). Als Name auf dunklem Grund
ist derselbe helle Ton besonders gut lesbar (8,0).
Der Erklaersatz im Fenster war damit falsch geworden ("Alle Toene
leuchten gleich stark") und sagt jetzt, was stimmt.
ZWEI PRUEFUNGEN WURDEN GENAUER:
pruef-chat-neu mass den HINTERGRUND der Mitte -- eine Darstellung,
die es nicht mehr gibt. Sie misst jetzt die Schriftfarbe und rechnet
die Mischung nach. Dabei stolperte sie ueber eine dritte
Farbschreibweise: Chromium gibt `color-mix`-Ergebnisse als
`color(srgb 0.676 0.645 0.504)` zurueck. Die Zeile war rot, obwohl
die Farbe auf den Bildpunkt genau stimmte -- ein Fehlalarm, der
teurer ist als ein echter Befund, weil man am Aussehen sucht und der
Fehler im Lesegeraet liegt.
Und sie prueft nicht mehr 360, sondern 360 x 7 -- nur den Grundton zu
messen hiesse, sechs Siebtel ungeprueft auszuliefern.
Geprueft: pruef-chat-anhaenge (123), pruef-chat-neu (36),
pruef-chatkachel (40), pruef-chat, pruef-chat-ausbau (69),
pruef-chat-optik, pruef-tippziele (11), pruef-css-klassen.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -4261,7 +4261,37 @@
|
||||
}
|
||||
|
||||
/* ---- Die Sprachnachricht in der Blase ------------------------------ */
|
||||
/* DIE SPRACHNACHRICHT BRAUCHT EINE MINDESTBREITE (25.09.2026).
|
||||
|
||||
Gefunden hat das pruef-chat-anhaenge, nicht ein Blick: „breit genug,
|
||||
um den Schieber zu treffen (165 px)" -- verlangt sind 200.
|
||||
|
||||
URSACHE WAR EINE FOLGE, keine Aenderung an dieser Stelle: Die Blase
|
||||
ist so breit wie ihr breitester Inhalt. Solange unter jeder
|
||||
Nachricht fuenf WOERTER standen, war das die Handgriff-Reihe mit
|
||||
ueber 400 px. Seit sie Zeichen sind (123 px), bestimmt das
|
||||
Abspielgeraet selbst die Breite -- und das nimmt sich, was da ist.
|
||||
|
||||
Das ist die Sorte Nebenwirkung, die man nie vorhersieht und immer
|
||||
misst: Eine Reihe kuerzer zu machen hat einen Schieber schmaler
|
||||
gemacht, drei Bildschirme weiter.
|
||||
|
||||
240 UND NICHT 200: Die Zahl in der Pruefung ist die Untergrenze,
|
||||
nicht das Ziel. Wer genau auf die Grenze baut, ist beim naechsten
|
||||
Pixel wieder darunter.
|
||||
|
||||
KEIN `min(240px, 100%)` -- der erste Anlauf stand so da und hat
|
||||
nichts getan. `100%` ist die Breite des Elternteils, und der ist ja
|
||||
gerade der schmale: `min(240, 165)` ist 165. Eine Mindestbreite, die
|
||||
sich am zu Schmalen orientiert, ist keine. Die feste Zahl zwingt die
|
||||
Blase zu wachsen -- genau das ist gemeint.
|
||||
|
||||
AUF DEM HANDY WIRD SIE ZURUECKGENOMMEN (unten in der schmalen
|
||||
Fassung): Dort ist die Blase selbst nur rund 250 px breit, und
|
||||
240 px plus Polsterung passen nicht mehr hinein. */
|
||||
.chat-ton {
|
||||
min-width: 240px;
|
||||
|
||||
display: grid; gap: 6px;
|
||||
/* So breit, dass der Schieber des Abspielgeräts bedienbar ist, und
|
||||
nicht breiter als eine Blase am Handy. */
|
||||
@@ -4533,7 +4563,92 @@
|
||||
pointer-events: none;
|
||||
box-shadow: 0 0 0 1px color-mix(in srgb, #000 45%, transparent);
|
||||
}
|
||||
.kachelrad__probe { opacity: .95; }
|
||||
/* ==== DIE PROBE ZEIGT, WIE ES WIRKLICH AUSSIEHT (25.09.2026) ======
|
||||
|
||||
Hier stand eine gefuellte Flaeche mit heller Schrift darauf. So sah
|
||||
die Blase bis zum 25.09. aus -- seither ist sie fuer alle dunkles
|
||||
Glas, und der gewaehlte Ton ist der NAME darauf. Die Probe zeigte
|
||||
also etwas, das es nicht mehr gibt.
|
||||
|
||||
Jetzt steht hier genau die Rechnung aus der Blase: derselbe
|
||||
Blasengrund, und darauf der Ton, mit Weiss aufgehellt im selben
|
||||
Verhaeltnis (`--namen-anteil`). Wer eine Farbe waehlt, sieht die
|
||||
Schrift, die die anderen sehen werden.
|
||||
|
||||
UND ES IST DER GRUND, WARUM DIE SIEBEN HELLIGKEITEN GEHEN: Eine
|
||||
gefuellte Flaeche muesste Schrift tragen, und bei sehr hellen Toenen
|
||||
schafft das keine der beiden Schriftfarben mehr (gemessen 4,1 statt
|
||||
noetiger 7). Als NAME auf dunklem Grund ist derselbe helle Ton
|
||||
besonders gut lesbar (8,0). */
|
||||
.kachelrad__mitte {
|
||||
background: color-mix(in srgb, var(--blasengrund) 96%, transparent);
|
||||
}
|
||||
.kachelrad__probe {
|
||||
opacity: 1;
|
||||
font-weight: 800;
|
||||
letter-spacing: .04em;
|
||||
color: color-mix(in srgb,
|
||||
var(--probe-ton, var(--akzent)) var(--namen-anteil, 50%), #f2f8ff);
|
||||
}
|
||||
|
||||
/* ==== DIE HELLIGKEITSLEITER (25.09.2026) ==========================
|
||||
|
||||
Filipe: „ich will dass die leute auch heller und dunkler aussuchen
|
||||
koennen … so dass die leute viel krassere moeglichkeiten haben."
|
||||
|
||||
SIEBEN FELDER IN IHRER ECHTEN FARBE, nicht sieben graue Kaestchen
|
||||
mit Beschriftung: Man waehlt eine Farbe, also soll man Farben sehen.
|
||||
Sie faerben sich beim Drehen am Ring mit.
|
||||
|
||||
EINE LEISTE UND KEIN ZWEITER KREIS: Farbton laeuft rund (359 grenzt
|
||||
an 0), Helligkeit nicht -- sie hat ein dunkles und ein helles Ende.
|
||||
Eine runde Form fuer etwas, das gerade verlaeuft, waere eine Form,
|
||||
die luegt. */
|
||||
.kachelhell {
|
||||
margin: 14px auto 0;
|
||||
max-width: 320px;
|
||||
display: grid; gap: 7px;
|
||||
}
|
||||
.kachelhell__schild {
|
||||
font-size: .74rem; font-weight: 700;
|
||||
letter-spacing: .1em; text-transform: uppercase;
|
||||
color: var(--text-still);
|
||||
}
|
||||
.kachelhell__leiter {
|
||||
display: grid; grid-template-columns: repeat(7, 1fr);
|
||||
gap: 4px;
|
||||
padding: 5px;
|
||||
border-radius: 14px;
|
||||
background: rgba(0, 0, 0, .3);
|
||||
box-shadow: inset 0 2px 5px -3px rgba(0, 0, 0, .9);
|
||||
cursor: pointer;
|
||||
}
|
||||
.kachelhell__leiter:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
|
||||
/* 44 px hoch: Hier tippt man mit dem Daumen, und sieben Felder
|
||||
nebeneinander sind ohnehin schon schmal. */
|
||||
.kachelhell__feld {
|
||||
height: 44px;
|
||||
border-radius: 9px;
|
||||
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08);
|
||||
transition: transform .14s ease, box-shadow .14s ease;
|
||||
}
|
||||
/* DIE WAHL STEHT HOEHER, sie ist nicht nur umrandet: Bei sieben
|
||||
benachbarten Farbfeldern ist ein Rahmen mehr die achte Farbe. Ein
|
||||
angehobenes Feld mit Lichtkante liest sich als „das hier". */
|
||||
.kachelhell__feld[data-an="ja"] {
|
||||
transform: translateY(-3px);
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, .5),
|
||||
0 0 0 2px rgba(255, 255, 255, .85),
|
||||
0 8px 16px -8px rgba(0, 0, 0, .9);
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.kachelhell__feld { transition: none; }
|
||||
}
|
||||
@media (forced-colors: active) {
|
||||
.kachelhell__feld { border: 1px solid CanvasText; }
|
||||
.kachelhell__feld[data-an="ja"] { border: 3px solid Highlight; }
|
||||
}
|
||||
|
||||
/* Ein Wechsel der Farbe soll nicht springen, aber auch nicht
|
||||
nachlaufen -- 90 ms sind gerade so viel, dass es weich wirkt. */
|
||||
@@ -5243,6 +5358,10 @@
|
||||
-webkit-mask-size: 15px 15px;
|
||||
mask-size: 15px 15px;
|
||||
}
|
||||
/* Die Mindestbreite der Sprachnachricht (240 px) gilt am Rechner.
|
||||
Hier ist die Blase selbst nur rund 250 px breit -- 240 plus
|
||||
Polsterung passen nicht mehr hinein und wuerden sie aufschieben. */
|
||||
.chat-ton { min-width: 0; width: 100%; }
|
||||
/* Die Uhrzeit gibt ihr Schild ab: Auf dem Handy zaehlt jede
|
||||
Polsterung, und die Trennung zwischen Angabe und Knopf macht
|
||||
hier ohnehin schon die Reihenfolge. */
|
||||
@@ -5266,3 +5385,157 @@
|
||||
Medienabfrage allein erhoeht die Spezifitaet nicht. */
|
||||
.chat__kopf .chat__kopf-zeichen { display: none; }
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
=====================================================================
|
||||
DIE BILDSCHAU (25.09.2026)
|
||||
=====================================================================
|
||||
=====================================================================
|
||||
|
||||
Filipe: „wenn man bilder aufmacht, will ich dass die in der mitte
|
||||
sind. beim hochformat soll links der husky sein und rechts der hase
|
||||
und beim querformat soll oben dogfather und unten team dogi stehen
|
||||
da wo platz ist. … ich will nicht dahin geschmissen sondern was
|
||||
richtig geiles mit einem geilen hintergrund."
|
||||
|
||||
DER GRUND IST DREI SCHICHTEN, nicht eine Farbe: ein tiefer Verlauf,
|
||||
drei weiche Lichter (violett, tuerkis, ein warmer Rest) und ein
|
||||
Schleier ganz aussen. Zusammen unter zehn Prozent Deckung -- ein
|
||||
Foto soll darauf liegen, nicht dagegen ankaempfen.
|
||||
|
||||
KEIN REINES SCHWARZ. Genau das zeigt der Browser von sich aus, und
|
||||
genau daran hat Filipe es gemerkt. Schwarz ist keine Gestaltung,
|
||||
sondern ihr Fehlen.
|
||||
===================================================================== */
|
||||
.bildschau {
|
||||
width: 100vw; max-width: 100vw;
|
||||
height: 100dvh; max-height: 100dvh;
|
||||
padding: 0; margin: 0; border: 0;
|
||||
background: none;
|
||||
overflow: hidden;
|
||||
color: var(--text, #e8f1fa);
|
||||
}
|
||||
.bildschau::backdrop { background: rgba(3, 4, 9, .86); backdrop-filter: blur(6px); }
|
||||
|
||||
.bildschau__grund {
|
||||
position: absolute; inset: 0; z-index: 0;
|
||||
background:
|
||||
radial-gradient(70% 55% at 18% 8%, rgba(122, 92, 255, .16), transparent 66%),
|
||||
radial-gradient(62% 52% at 84% 88%, rgba(38, 200, 196, .13), transparent 68%),
|
||||
radial-gradient(48% 40% at 60% 46%, rgba(255, 176, 92, .06), transparent 70%),
|
||||
linear-gradient(168deg, #0a0b14 0%, #070811 55%, #05060c 100%);
|
||||
}
|
||||
/* Ein Schleier von aussen nach innen -- er zieht den Blick in die
|
||||
Mitte, ohne dass man ihn als Rahmen bemerkt. */
|
||||
.bildschau__grund::after {
|
||||
content: ""; position: absolute; inset: 0;
|
||||
background: radial-gradient(120% 95% at 50% 50%, transparent 52%, rgba(0, 0, 0, .55) 100%);
|
||||
}
|
||||
|
||||
/* ---- Die Buehne: das Bild sitzt in der MITTE ----------------------- */
|
||||
.bildschau__buehne {
|
||||
position: absolute; inset: 0; z-index: 2;
|
||||
display: grid; place-items: center;
|
||||
padding: 72px 4vw 56px;
|
||||
}
|
||||
.bildschau__bild {
|
||||
max-width: 92vw; max-height: 82dvh;
|
||||
width: auto; height: auto;
|
||||
border-radius: 14px;
|
||||
/* Ein feiner heller Saum trennt das Foto vom Grund, auch wenn seine
|
||||
Raender selbst dunkel sind. Ohne ihn franst ein dunkles Foto in
|
||||
den Hintergrund aus, und man sieht nicht mehr, wo es aufhoert. */
|
||||
box-shadow:
|
||||
0 0 0 1px rgba(255, 255, 255, .1),
|
||||
0 40px 90px -40px rgba(0, 0, 0, .95),
|
||||
0 0 90px -40px rgba(122, 92, 255, .5);
|
||||
}
|
||||
|
||||
/* ---- Die Begleiter ------------------------------------------------- */
|
||||
/* Sie liegen HINTER dem Bild (z-index 1 gegen 2) -- ein Husky, der
|
||||
ueber einem Foto liegt, waere keine Zierde, sondern ein Hindernis. */
|
||||
.bildschau__figur {
|
||||
position: absolute; bottom: 0; z-index: 1;
|
||||
height: min(78dvh, 720px);
|
||||
width: auto;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity .32s ease;
|
||||
}
|
||||
.bildschau__figur--links { left: 0; }
|
||||
/* NICHT SPIEGELN. Der erste Anlauf drehte den Hasen um, damit beide
|
||||
„nach innen" schauen -- ein alter Reflex aus dem Plakatsatz. Auf dem
|
||||
Probebild stand danach „Hasi Dog" seitenverkehrt auf seinem Hoodie.
|
||||
Beide Figuren sehen ohnehin nach vorn; es gibt nichts zu spiegeln,
|
||||
und Schrift im Bild spiegelt man nie. */
|
||||
.bildschau__figur--rechts { right: 0; }
|
||||
.bildschau[data-lage="hoch"] .bildschau__figur { opacity: .92; }
|
||||
|
||||
/* ---- Die zwei Schriftzuege ----------------------------------------- */
|
||||
.bildschau__wort {
|
||||
position: absolute; left: 0; right: 0; z-index: 1;
|
||||
display: flex; align-items: center; justify-content: center; gap: 14px;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity .32s ease;
|
||||
}
|
||||
.bildschau__wort--oben { top: 18px; }
|
||||
.bildschau__wort--unten { bottom: 16px; }
|
||||
.bildschau[data-lage="quer"] .bildschau__wort { opacity: 1; }
|
||||
.bildschau__zeichen { width: 34px; height: 34px; filter: invert(1) opacity(.72); }
|
||||
/* GESPERRT UND GROSS: Ein Schriftzug ist kein Satz. Die Sperrung macht
|
||||
aus zwei Woertern ein Zeichen -- man liest es nicht, man erkennt es. */
|
||||
.bildschau__wort-text {
|
||||
font-size: clamp(1.1rem, 2.6vw, 1.9rem);
|
||||
font-weight: 800;
|
||||
letter-spacing: .34em;
|
||||
text-transform: uppercase;
|
||||
color: rgba(232, 241, 250, .5);
|
||||
text-shadow: 0 0 26px rgba(122, 92, 255, .45);
|
||||
}
|
||||
.bildschau__wort--unten .bildschau__wort-text {
|
||||
font-size: clamp(.9rem, 2vw, 1.4rem);
|
||||
letter-spacing: .42em;
|
||||
color: rgba(232, 241, 250, .34);
|
||||
}
|
||||
|
||||
/* ---- Die Leiste ---------------------------------------------------- */
|
||||
.bildschau__leiste {
|
||||
position: absolute; top: 0; left: 0; right: 0; z-index: 3;
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
padding: 12px 14px;
|
||||
background: linear-gradient(180deg, rgba(4, 5, 11, .78), transparent);
|
||||
}
|
||||
.bildschau__name {
|
||||
flex: 1; min-width: 0;
|
||||
font-size: .86rem; color: rgba(232, 241, 250, .7);
|
||||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||||
}
|
||||
/* 44 px hoch, auch am Rechner: Der Schliessen-Knopf ist der einzige
|
||||
Weg heraus, den man SIEHT (Escape kennt nicht jeder). */
|
||||
.bildschau__knopf {
|
||||
flex: none;
|
||||
min-height: 44px; padding: 0 14px;
|
||||
display: inline-flex; align-items: center;
|
||||
border: 1px solid rgba(255, 255, 255, .12);
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, .06);
|
||||
color: var(--text, #e8f1fa);
|
||||
font: inherit; font-size: .84rem; font-weight: 600;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.bildschau__knopf:hover { background: rgba(255, 255, 255, .13); }
|
||||
.bildschau__knopf:focus-visible { outline: 2px solid #b9a7ff; outline-offset: 2px; }
|
||||
.bildschau__zu { min-width: 44px; justify-content: center; padding: 0; font-size: 1rem; }
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.bildschau__figur, .bildschau__wort { transition: none; }
|
||||
}
|
||||
/* Auf einem Telefon fuellt ein Foto den Schirm -- dort gibt es keinen
|
||||
Platz fuer Begleiter, und die Schau sagt das ueber `data-lage`
|
||||
ohnehin selbst. Hier bleibt nur die Buehne enger. */
|
||||
@media (max-width: 620px) {
|
||||
.bildschau__buehne { padding: 64px 12px 24px; }
|
||||
.bildschau__bild { max-width: 96vw; max-height: 78dvh; }
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
@@ -0,0 +1,234 @@
|
||||
/* =====================================================================
|
||||
DIE BILDSCHAU (25.09.2026)
|
||||
=====================================================================
|
||||
|
||||
Filipe: „wenn man bilder aufmacht, will ich dass die in der mitte
|
||||
sind. beim hochformat soll links der husky sein und rechts der hase
|
||||
und beim querformat soll oben dogfather und unten team dogi stehen
|
||||
da wo platz ist. es soll richtig geil gemacht werden alles … ich
|
||||
will nicht dahin geschmissen sondern was richtig geiles mit einem
|
||||
geilen hintergrund."
|
||||
|
||||
---------------------------------------------------------------------
|
||||
WAS VORHER PASSIERTE
|
||||
|
||||
Ein Klick auf ein Foto oeffnete die Datei selbst in einem neuen Tab.
|
||||
Was man dann sah, war nicht unsere Seite, sondern die eingebaute
|
||||
Bildanzeige des Browsers: schwarzer Grund, Bild oben links in der
|
||||
Ecke, Dateiname in der Titelleiste. Auf Filipes Bildschirmfoto nimmt
|
||||
das Foto die linke Haelfte ein, rechts sind 1200 px Schwarz.
|
||||
|
||||
Das ist kein Fehler im Browser -- er zeigt eine Datei, und eine
|
||||
Datei hat keine Gestaltung. Wer Gestaltung will, muss eine SEITE
|
||||
zeigen.
|
||||
|
||||
---------------------------------------------------------------------
|
||||
WARUM EINE SCHAU IN DER SEITE UND KEIN ZWEITER TAB
|
||||
|
||||
Ein zweiter Tab braucht eine eigene Seite, eine eigene Anmeldung und
|
||||
einen eigenen Weg zurueck. Die Schau liegt UEBER dem Chat: Man ist
|
||||
mit Escape wieder da, wo man war, und das Gespraech laeuft im
|
||||
Hintergrund weiter.
|
||||
|
||||
DER WEG IN DEN TAB BLEIBT TROTZDEM. Das Foto haengt weiterhin an
|
||||
einem echten Verweis mit `target="_blank"` -- mittlere Maustaste,
|
||||
„In neuem Tab oeffnen" und Herunterladen funktionieren wie vorher.
|
||||
Abgefangen wird nur der GEWOEHNLICHE Klick. Ein Verweis, der kein
|
||||
Verweis mehr ist, nimmt Leuten Wege weg, die sie seit Jahren kennen.
|
||||
|
||||
---------------------------------------------------------------------
|
||||
WARUM `<dialog>` UND KEIN EIGENES DIV
|
||||
|
||||
`showModal()` bringt drei Dinge mit, die man sonst von Hand baut und
|
||||
dabei vergisst: Escape schliesst, der Tastaturfokus bleibt drin, und
|
||||
alles dahinter ist fuer Vorleseprogramme stumm. Drei eigene
|
||||
Loesungen waeren drei Gelegenheiten fuer einen Fehler.
|
||||
|
||||
---------------------------------------------------------------------
|
||||
DIE BEGLEITER
|
||||
|
||||
HOCHFORMAT: Husky links, Hase rechts. Dort ist der Platz -- ein
|
||||
hohes Foto laesst links und rechts je ein Viertel des Bildschirms
|
||||
frei.
|
||||
|
||||
QUERFORMAT: „DogFather" oben, „Team Dogi" unten. Dort ist der Platz
|
||||
-- ein breites Foto laesst oben und unten Streifen frei.
|
||||
|
||||
SIE ERSCHEINEN NUR, WENN WIRKLICH PLATZ IST. Gemessen wird nicht die
|
||||
Fensterbreite, sondern der Rest neben dem Bild: Ein hohes Foto auf
|
||||
einem Telefon fuellt den Schirm, und ein Husky, der darueberliegt,
|
||||
waere keine Zierde, sondern ein Hindernis.
|
||||
|
||||
SIE SIND LEISE. `aria-hidden` -- ein Vorleseprogramm soll nicht
|
||||
„Grafik Husky" sagen, wenn jemand ein Foto ansehen will. Und sie
|
||||
liegen HINTER dem Bild, nie darauf.
|
||||
===================================================================== */
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var schau = null; // das <dialog>, einmal gebaut und wiederverwendet
|
||||
var teile = null; // { bild, name, tab, husky, hase, oben, unten }
|
||||
var zurueck = null; // wohin der Fokus nach dem Schliessen gehoert
|
||||
|
||||
function el(art, klasse, text) {
|
||||
var e = document.createElement(art);
|
||||
if (klasse) e.className = klasse;
|
||||
if (text != null) e.textContent = text;
|
||||
return e;
|
||||
}
|
||||
|
||||
function bauen() {
|
||||
if (schau) return;
|
||||
schau = document.createElement('dialog');
|
||||
schau.className = 'bildschau';
|
||||
schau.setAttribute('aria-label', 'Bild ansehen');
|
||||
|
||||
/* DER HINTERGRUND IST EIN EIGENES STUECK und nicht der Grund des
|
||||
Dialogs: Er soll sich unabhaengig vom Inhalt bewegen duerfen
|
||||
(Verlauf, Schleier, Koernung), ohne dass der Inhalt etwas davon
|
||||
erbt. */
|
||||
var grund = el('div', 'bildschau__grund');
|
||||
grund.setAttribute('aria-hidden', 'true');
|
||||
schau.appendChild(grund);
|
||||
|
||||
/* Die Begleiter liegen HINTER dem Bild -- eigene Ebene, damit das
|
||||
Bild in jedem Fall obenauf ist. */
|
||||
var husky = el('img', 'bildschau__figur bildschau__figur--links');
|
||||
husky.src = 'assets/img/schau-husky.webp';
|
||||
husky.alt = '';
|
||||
husky.setAttribute('aria-hidden', 'true');
|
||||
husky.loading = 'lazy';
|
||||
husky.decoding = 'async';
|
||||
var hase = el('img', 'bildschau__figur bildschau__figur--rechts');
|
||||
hase.src = 'assets/img/schau-hase.webp';
|
||||
hase.alt = '';
|
||||
hase.setAttribute('aria-hidden', 'true');
|
||||
hase.loading = 'lazy';
|
||||
hase.decoding = 'async';
|
||||
schau.appendChild(husky);
|
||||
schau.appendChild(hase);
|
||||
|
||||
/* Die zwei Schriftzuege fuers Querformat. */
|
||||
var oben = el('div', 'bildschau__wort bildschau__wort--oben');
|
||||
oben.setAttribute('aria-hidden', 'true');
|
||||
var zeichen = el('img', 'bildschau__zeichen');
|
||||
zeichen.src = 'assets/img/marke-husky.webp';
|
||||
zeichen.alt = '';
|
||||
oben.appendChild(zeichen);
|
||||
oben.appendChild(el('span', 'bildschau__wort-text', 'DogFather'));
|
||||
var unten = el('div', 'bildschau__wort bildschau__wort--unten');
|
||||
unten.setAttribute('aria-hidden', 'true');
|
||||
unten.appendChild(el('span', 'bildschau__wort-text', 'Team Dogi'));
|
||||
schau.appendChild(oben);
|
||||
schau.appendChild(unten);
|
||||
|
||||
var buehne = el('div', 'bildschau__buehne');
|
||||
var bild = el('img', 'bildschau__bild');
|
||||
bild.alt = '';
|
||||
buehne.appendChild(bild);
|
||||
schau.appendChild(buehne);
|
||||
|
||||
/* Die Leiste steht OBEN und nicht ueber dem Bild: Sie soll
|
||||
erreichbar sein, ohne etwas zu verdecken. */
|
||||
var leiste = el('div', 'bildschau__leiste');
|
||||
var name = el('span', 'bildschau__name');
|
||||
var tab = el('a', 'bildschau__knopf', 'Im Tab öffnen');
|
||||
tab.target = '_blank';
|
||||
tab.rel = 'noopener noreferrer';
|
||||
var zu = el('button', 'bildschau__knopf bildschau__zu');
|
||||
zu.type = 'button';
|
||||
zu.setAttribute('aria-label', 'Bild schließen');
|
||||
zu.title = 'Schließen (Esc)';
|
||||
zu.textContent = '✕';
|
||||
zu.addEventListener('click', function () { schau.close(); });
|
||||
leiste.appendChild(name);
|
||||
leiste.appendChild(tab);
|
||||
leiste.appendChild(zu);
|
||||
schau.appendChild(leiste);
|
||||
|
||||
/* EIN KLICK NEBEN DAS BILD SCHLIESST. Das erwartet jeder, der
|
||||
schon einmal ein Foto angesehen hat. Ein Klick AUF das Bild
|
||||
nicht -- sonst schliesst es sich, waehrend man hineinzoomt. */
|
||||
schau.addEventListener('click', function (e) {
|
||||
if (e.target === schau || e.target === grund || e.target === buehne) schau.close();
|
||||
});
|
||||
schau.addEventListener('close', function () {
|
||||
/* Die Quelle loesen: Ein grosses Foto im Speicher zu halten,
|
||||
nachdem niemand es mehr ansieht, ist Last ohne Zweck. */
|
||||
teile.bild.removeAttribute('src');
|
||||
if (zurueck && document.contains(zurueck)) {
|
||||
try { zurueck.focus(); } catch (f) { /* egal */ }
|
||||
}
|
||||
zurueck = null;
|
||||
});
|
||||
|
||||
document.body.appendChild(schau);
|
||||
teile = { bild: bild, name: name, tab: tab, husky: husky, hase: hase,
|
||||
oben: oben, unten: unten };
|
||||
}
|
||||
|
||||
/** Hoch, quer oder fast quadratisch -- und ist ueberhaupt Platz?
|
||||
*
|
||||
* GEMESSEN WIRD DER REST NEBEN DEM BILD, nicht die Fensterbreite.
|
||||
* Eine Schwelle wie „ab 1100 px zeigen" waere eine Rechnung von
|
||||
* gestern: Sie stimmt fuer ein 3:4-Foto und ist bei einem 9:16-Foto
|
||||
* auf demselben Schirm falsch. Dieses Haus ist an festen Breiten
|
||||
* schon dreimal hereingefallen.
|
||||
*/
|
||||
function lageBestimmen(b, h) {
|
||||
if (!(b > 0 && h > 0)) return 'keine';
|
||||
var fb = window.innerWidth, fh = window.innerHeight;
|
||||
/* So gross wird das Bild: es passt in 92 % Breite und 82 % Hoehe. */
|
||||
var masz = Math.min(fb * 0.92 / b, (fh * 0.82) / h);
|
||||
var zb = b * masz, zh = h * masz;
|
||||
var restSeite = (fb - zb) / 2;
|
||||
var restOben = (fh - zh) / 2;
|
||||
|
||||
if (h > b * 1.05) {
|
||||
/* Eine Figur braucht rund 170 px, damit sie eine Figur ist und
|
||||
kein Streifen. Weniger, und sie steht besser gar nicht da. */
|
||||
return restSeite >= 170 ? 'hoch' : 'keine';
|
||||
}
|
||||
if (b > h * 1.05) {
|
||||
/* Ein Schriftzug braucht rund 70 px Luft -- darunter klebt er am
|
||||
Bildrand und sieht aus wie ein Versehen. */
|
||||
return restOben >= 70 ? 'quer' : 'keine';
|
||||
}
|
||||
return restOben >= 70 ? 'quer' : 'keine';
|
||||
}
|
||||
|
||||
function lageSetzen() {
|
||||
if (!schau || !schau.open) return;
|
||||
var b = teile.bild.naturalWidth, h = teile.bild.naturalHeight;
|
||||
schau.dataset.lage = lageBestimmen(b, h);
|
||||
}
|
||||
|
||||
/** Ein Bild gross ansehen.
|
||||
* @param {{weg:string,name:string}} a das Bild
|
||||
* @param {Element} [woher] wohin der Fokus zurueckgeht
|
||||
*/
|
||||
function zeigen(a, woher) {
|
||||
if (!a || !a.weg) return;
|
||||
bauen();
|
||||
zurueck = woher || document.activeElement;
|
||||
teile.bild.src = a.weg;
|
||||
teile.bild.alt = a.name || 'Foto';
|
||||
teile.name.textContent = a.name || '';
|
||||
teile.tab.href = a.weg;
|
||||
schau.dataset.lage = 'keine';
|
||||
/* ERST WENN DAS BILD DA IST, steht sein Format fest. Vorher sind
|
||||
naturalWidth und naturalHeight null -- und „null zu null" waere
|
||||
weder hoch noch quer. Liegt es schon im Zwischenspeicher, ist
|
||||
`complete` sofort wahr und die Zeile darunter greift. */
|
||||
teile.bild.onload = lageSetzen;
|
||||
if (teile.bild.complete) lageSetzen();
|
||||
if (!schau.open) schau.showModal();
|
||||
}
|
||||
|
||||
/* Dreht jemand das Telefon oder zieht das Fenster kleiner, aendert
|
||||
sich der Platz -- und damit die Antwort auf „passt eine Figur
|
||||
daneben". */
|
||||
window.addEventListener('resize', lageSetzen);
|
||||
|
||||
window.Bildschau = { zeigen: zeigen };
|
||||
})();
|
||||
+225
-8
@@ -57,6 +57,31 @@
|
||||
/* Die 360 Farben des Rings, Index = Winkel. Kommt vom Server; hier
|
||||
wird nichts gerechnet (Begruendung steht an der Route). */
|
||||
let kreisToene = [];
|
||||
/* Die sieben Helligkeiten und welche davon die Mitte ist. Beides
|
||||
kommt vom Server (siehe chat-kreis-stufen.js). */
|
||||
let kreisStufen = [{ wert: 's4', misch: 0, name: 'normal' }];
|
||||
let kreisMitte = 's4';
|
||||
|
||||
/** Einen Grundton heller oder dunkler mischen.
|
||||
*
|
||||
* `misch` ist negativ fuer dunkler (Richtung Schwarz) und positiv
|
||||
* fuer heller (Richtung Weiss) -- dieselbe Rechnung wie
|
||||
* `color-mix(in srgb, …)` und wie `tonFarbe()` im Server. Sie steht
|
||||
* hier ein zweites Mal, und das ist Absicht: Die ZAHLEN kommen vom
|
||||
* Server, nur das Mischen selbst passiert im Browser. Eine Farbe,
|
||||
* die 2520-mal ueber die Leitung geht, waere teurer als drei Zeilen
|
||||
* Rechnung.
|
||||
*/
|
||||
function tonMischen(grund, misch) {
|
||||
const s = String(grund).replace('#', '');
|
||||
if (s.length !== 6) return grund;
|
||||
const teile = [0, 2, 4].map((i) => parseInt(s.slice(i, i + 2), 16));
|
||||
const ziel = misch < 0 ? 0 : 255;
|
||||
const t = Math.abs(misch);
|
||||
return '#' + teile
|
||||
.map((v) => Math.round(v * (1 - t) + ziel * t).toString(16).padStart(2, '0'))
|
||||
.join('');
|
||||
}
|
||||
let meineKachel = null;
|
||||
let autoKachel = null;
|
||||
|
||||
@@ -86,9 +111,39 @@
|
||||
Eine Sonderbehandlung an zehn Stellen waere neun Gelegenheiten
|
||||
gewesen, eine davon zu vergessen. */
|
||||
kreisToene = Array.isArray(d.kreis) ? d.kreis : [];
|
||||
/* ==== DIE SIEBEN HELLIGKEITEN (25.09.2026) ==================
|
||||
|
||||
Filipe: „ich will dass die leute auch heller und dunkler
|
||||
aussuchen koennen."
|
||||
|
||||
NICHT 2520 FERTIGE FARBEN, sondern 360 Grundtoene und sieben
|
||||
Mischanteile -- die ganze Tabelle waere 20 kB fuer etwas, das
|
||||
eine Zeile Rechnung ist.
|
||||
|
||||
DIE ZAHLEN KOMMEN VOM SERVER und stehen nicht hier: Sie sind
|
||||
aus der Kontrastrechnung hergeleitet (chat-kreis-stufen.js),
|
||||
und eine zweite Fassung im Browser waere ab der naechsten
|
||||
Messung falsch -- unbemerkt, denn sie lieferte ja weiter
|
||||
„irgendeine Farbe". Kommt nichts, bleibt es bei der einen
|
||||
Mitte: der Kreis von gestern. */
|
||||
kreisStufen = Array.isArray(d.kreis_stufen) && d.kreis_stufen.length
|
||||
? d.kreis_stufen : [{ wert: 's4', misch: 0, name: 'normal' }];
|
||||
kreisMitte = d.kreis_mitte || 's4';
|
||||
kreisToene.forEach((farbe, winkel) => {
|
||||
KACHEL_FARBE['ton-' + winkel] = farbe;
|
||||
if (d.kreis_schrift) KACHEL_SCHRIFT['ton-' + winkel] = d.kreis_schrift;
|
||||
/* Jede Stufe bekommt ihren eigenen Schluessel in derselben
|
||||
Tabelle. Damit funktionieren ALLE Stellen, die eine Farbe
|
||||
nachschlagen, unveraendert weiter -- dieselbe Ueberlegung
|
||||
wie am 23.09., als der Kreis dazukam. */
|
||||
for (const s of kreisStufen) {
|
||||
if (!s.misch) continue;
|
||||
KACHEL_FARBE['ton-' + winkel + '-' + s.wert] = tonMischen(farbe, s.misch);
|
||||
}
|
||||
/* Und der Schluessel MIT der Mitte zeigt auf dieselbe Farbe
|
||||
wie der ohne -- sonst waere „ton-214" und „ton-214-s4"
|
||||
zweierlei, und beide kaemen vor. */
|
||||
KACHEL_FARBE['ton-' + winkel + '-' + kreisMitte] = farbe;
|
||||
});
|
||||
kachelKnopfZeigen();
|
||||
} catch { /* ohne die Liste bleibt alles beim Standard -- kein Grund
|
||||
@@ -300,8 +355,22 @@
|
||||
zwischen zwei geprueften Werten liegt.
|
||||
===================================================================== */
|
||||
let radWinkel = 0;
|
||||
/* Welche der sieben Helligkeiten gerade gilt. Der Ring bestimmt den
|
||||
Farbton, die Leiter die Helligkeit -- zwei Achsen derselben
|
||||
Farbe. */
|
||||
let radStufe = 's4';
|
||||
let radUhr = null;
|
||||
|
||||
/** Der Schluessel aus beidem. Die Mitte bekommt KEINEN Zusatz:
|
||||
* „ton-214" ist seit dem 23.09. der gueltige Schluessel, und wer
|
||||
* ihn traegt, soll nach diesem Umbau nicht ploetzlich einen anderen
|
||||
* in der Datenbank stehen haben. */
|
||||
function radSchluessel() {
|
||||
return radStufe === kreisMitte
|
||||
? 'ton-' + radWinkel
|
||||
: 'ton-' + radWinkel + '-' + radStufe;
|
||||
}
|
||||
|
||||
function radBauen() {
|
||||
const ring = $('kachelrad-ring');
|
||||
const rad = $('kachelrad');
|
||||
@@ -318,8 +387,13 @@
|
||||
Wer Babyblau traegt, hat keinen Winkel -- dann zeigt der Griff
|
||||
auf den naechstgelegenen, ohne dass etwas umgestellt wird. */
|
||||
const jetzt = KACHEL_FARBE[meineKachel] || KACHEL_FARBE[autoKachel] || null;
|
||||
const t = /^ton-(\d{1,3})$/.exec(String(meineKachel || ''));
|
||||
/* Der Schluessel darf seit dem 25.09.2026 eine Stufe tragen
|
||||
("ton-214-s6"). Ohne Zusatz gilt die Mitte -- so wie der Server
|
||||
es auch liest. */
|
||||
const t = /^ton-(\d{1,3})(?:-(s[1-7]))?$/.exec(String(meineKachel || ''));
|
||||
radWinkel = t ? Number(t[1]) : (jetzt ? naechsterWinkel(jetzt).winkel : 0);
|
||||
radStufe = (t && t[2]) || kreisMitte;
|
||||
leiterBauen();
|
||||
radZeigen(radWinkel, { nurAnzeige: true });
|
||||
}
|
||||
|
||||
@@ -333,24 +407,138 @@
|
||||
ring.setAttribute('aria-valuenow', String(w));
|
||||
/* EINE ZAHL IN GRAD SAGT NIEMANDEM ETWAS. Vorgelesen wird der
|
||||
Farbname, den ein Mensch benutzt -- "Blaugruen, 190 Grad". */
|
||||
ring.setAttribute('aria-valuetext', farbwort(w) + ', ' + w + ' Grad');
|
||||
/* DIE HELLIGKEIT GEHOERT IN DEN VORLESETEXT. Ohne sie saegte eine
|
||||
Sprachausgabe bei allen sieben Stufen dasselbe -- und man haette
|
||||
kein Mittel, die Wahl zu hoeren. */
|
||||
ring.setAttribute('aria-valuetext',
|
||||
farbwort(w) + ', ' + w + ' Grad, ' + stufenName(radStufe));
|
||||
if (mitte) {
|
||||
const farbe = kreisToene[w];
|
||||
mitte.style.background = farbe || '';
|
||||
const s = KACHEL_SCHRIFT['ton-' + w];
|
||||
mitte.style.color = (s && s.text) || '';
|
||||
/* ==== DIE PROBE ZEIGT, WIE ES WIRKLICH AUSSIEHT (25.09.2026)
|
||||
|
||||
Hier stand eine gefuellte Flaeche in der gewaehlten Farbe mit
|
||||
heller Schrift darauf. So sah die Blase bis zum 25.09. aus --
|
||||
seither ist sie fuer alle dunkles Glas, und der gewaehlte Ton
|
||||
ist der NAME darauf.
|
||||
|
||||
Die Probe zeigte also etwas, das es nicht mehr gibt. Jetzt
|
||||
zeigt sie genau die Rechnung aus chat.css: der Ton, mit Weiss
|
||||
aufgehellt (`--namen-anteil`), auf dem Blasengrund. Wer hier
|
||||
eine Farbe waehlt, sieht die Schrift, die die anderen im Chat
|
||||
sehen werden.
|
||||
|
||||
NEBENWIRKUNG, UND SIE IST DER GRUND, WARUM DIE HELLIGKEITEN
|
||||
UEBERHAUPT GEHEN: Eine gefuellte Flaeche muesste Schrift
|
||||
tragen -- und bei sehr hellen Toenen schafft das keine der
|
||||
beiden Schriftfarben mehr (gemessen: 4,1 statt noetiger 7).
|
||||
Als NAME auf dunklem Grund ist derselbe helle Ton dagegen
|
||||
besonders gut lesbar (8,0). Die neue Probe ist damit nicht nur
|
||||
ehrlicher, sie macht die sieben Stufen erst moeglich. */
|
||||
const farbe = KACHEL_FARBE[radSchluessel()] || kreisToene[w];
|
||||
mitte.style.background = '';
|
||||
mitte.style.setProperty('--probe-ton', farbe || '');
|
||||
}
|
||||
if (!nurAnzeige) {
|
||||
/* Die eigenen Blasen im Verlauf faerben sich mit -- man
|
||||
entscheidet sich ja nicht fuer einen Fleck, sondern dafuer,
|
||||
wie die eigenen Nachrichten aussehen. */
|
||||
meineKachel = 'ton-' + w;
|
||||
meineKachel = radSchluessel();
|
||||
/* DIE LEITER FAERBT MIT. Ohne diese Zeile zeigten die sieben
|
||||
Felder die Helligkeiten des Tons von vorhin -- man waehlt
|
||||
Gruen und sieht sieben Rottoene darunter. */
|
||||
leiterZeigen();
|
||||
kachelKnopfZeigen();
|
||||
eigeneKachelnFaerben();
|
||||
auswahlMarkieren();
|
||||
}
|
||||
}
|
||||
|
||||
/** Der Name einer Helligkeitsstufe -- fuer Sprachausgabe und Titel. */
|
||||
function stufenName(wert) {
|
||||
return (kreisStufen.find((s) => s.wert === wert) || {}).name || 'normal';
|
||||
}
|
||||
|
||||
/* ==== DIE HELLIGKEITSLEITER (25.09.2026) =========================
|
||||
|
||||
Filipe: „ich will dass die leute auch heller und dunkler aussuchen
|
||||
koennen … so dass die leute viel krassere moeglichkeiten haben."
|
||||
|
||||
SIEBEN FELDER, JEDES IN SEINER ECHTEN FARBE -- nicht sieben graue
|
||||
Kaestchen mit Beschriftung. Man waehlt eine Farbe; also soll man
|
||||
Farben sehen. Die Felder faerben sich beim Drehen am Ring mit: Wer
|
||||
den Farbton aendert, sieht sofort, wie die sieben Helligkeiten
|
||||
DIESES Tons aussehen.
|
||||
|
||||
EINE LEISTE UND KEIN ZWEITER KREIS: Farbton laeuft rund (359 Grad
|
||||
grenzt an 0), Helligkeit nicht -- sie hat ein dunkles und ein
|
||||
helles Ende. Eine runde Form fuer etwas, das gerade verlaeuft,
|
||||
waere eine Form, die luegt.
|
||||
|
||||
`role="slider"` AM GANZEN KASTEN und nicht sieben Knoepfe: Es ist
|
||||
EIN Wert mit sieben Stufen. Sieben Knoepfe waeren sieben
|
||||
Tabulatorschritte fuer eine Entscheidung. */
|
||||
function leiterBauen() {
|
||||
const leiter = $('kachelhell-leiter');
|
||||
if (!leiter) return;
|
||||
leiter.textContent = '';
|
||||
kreisStufen.forEach((s, i) => {
|
||||
const feld = el('span', 'kachelhell__feld');
|
||||
feld.dataset.stufe = s.wert;
|
||||
feld.title = s.name;
|
||||
/* aria-hidden: Der Wert steht am Kasten (`aria-valuenow`), die
|
||||
Felder sind seine Darstellung. Ohne das laese eine Sprachausgabe
|
||||
sieben leere Felder vor. */
|
||||
feld.setAttribute('aria-hidden', 'true');
|
||||
feld.addEventListener('click', () => stufeWaehlen(i, true));
|
||||
leiter.append(feld);
|
||||
});
|
||||
leiterZeigen();
|
||||
}
|
||||
|
||||
/** Die Felder auf den aktuellen Farbton bringen und die Wahl zeigen. */
|
||||
function leiterZeigen() {
|
||||
const leiter = $('kachelhell-leiter');
|
||||
if (!leiter) return;
|
||||
const nr = Math.max(0, kreisStufen.findIndex((s) => s.wert === radStufe));
|
||||
leiter.setAttribute('aria-valuenow', String(nr + 1));
|
||||
leiter.setAttribute('aria-valuetext', stufenName(radStufe));
|
||||
for (const feld of leiter.children) {
|
||||
const s = kreisStufen.find((x) => x.wert === feld.dataset.stufe);
|
||||
const grund = kreisToene[radWinkel];
|
||||
if (s && grund) feld.style.background = s.misch ? tonMischen(grund, s.misch) : grund;
|
||||
feld.dataset.an = feld.dataset.stufe === radStufe ? 'ja' : 'nein';
|
||||
}
|
||||
}
|
||||
|
||||
/** Eine Stufe waehlen -- ueber den Index, damit Pfeiltasten und
|
||||
* Klick denselben Weg gehen. */
|
||||
function stufeWaehlen(nr, sichern) {
|
||||
const n = Math.max(0, Math.min(kreisStufen.length - 1, nr));
|
||||
radStufe = kreisStufen[n].wert;
|
||||
radZeigen(radWinkel);
|
||||
leiterZeigen();
|
||||
if (sichern) radSichern(0);
|
||||
}
|
||||
|
||||
function leiterBedienen() {
|
||||
const leiter = $('kachelhell-leiter');
|
||||
if (!leiter) return;
|
||||
leiter.addEventListener('keydown', (e) => {
|
||||
const nr = kreisStufen.findIndex((s) => s.wert === radStufe);
|
||||
let ziel = null;
|
||||
if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') ziel = nr - 1;
|
||||
else if (e.key === 'ArrowRight' || e.key === 'ArrowUp') ziel = nr + 1;
|
||||
else if (e.key === 'Home') ziel = 0;
|
||||
else if (e.key === 'End') ziel = kreisStufen.length - 1;
|
||||
if (ziel === null) return;
|
||||
e.preventDefault();
|
||||
/* Mit einer halben Sekunde Ruhe speichern -- wer mit der Taste
|
||||
durch die Stufen faehrt, soll nicht sieben Anfragen ausloesen.
|
||||
Dieselbe Ueberlegung wie am Ring. */
|
||||
stufeWaehlen(ziel, false);
|
||||
radSichern(500);
|
||||
});
|
||||
}
|
||||
|
||||
/** Ein Wort fuer den Bereich, damit eine Sprachausgabe etwas sagen kann. */
|
||||
function farbwort(w) {
|
||||
const namen = [
|
||||
@@ -367,7 +555,7 @@
|
||||
/** Nach der Bewegung einmal speichern. */
|
||||
function radSichern(verzoegerung = 0) {
|
||||
clearTimeout(radUhr);
|
||||
radUhr = setTimeout(() => kachelSetzen('ton-' + radWinkel), verzoegerung);
|
||||
radUhr = setTimeout(() => kachelSetzen(radSchluessel()), verzoegerung);
|
||||
}
|
||||
|
||||
function radBedienen() {
|
||||
@@ -416,6 +604,7 @@
|
||||
|
||||
function kachelwahlBedienen() {
|
||||
radBedienen();
|
||||
leiterBedienen();
|
||||
const knopf = $('kachel-oeffnen'), dlg = $('kachel-wahl'), zu = $('kachel-zu');
|
||||
if (!knopf || !dlg) return;
|
||||
knopf.addEventListener('click', () => { kachelwahlBauen(); dlg.showModal(); });
|
||||
@@ -2257,6 +2446,34 @@
|
||||
kasten.style.maxWidth = `${breit}px`;
|
||||
}
|
||||
|
||||
/* ==== EIN KLICK OEFFNET DIE SCHAU (25.09.2026) ================
|
||||
|
||||
Filipe: „wenn man bilder aufmacht, will ich dass die in der
|
||||
mitte sind."
|
||||
|
||||
Bis heute fuehrte der Verweis auf die DATEI, und was man dann
|
||||
sah, war die eingebaute Bildanzeige des Browsers: schwarzer
|
||||
Grund, Bild in der Ecke. Das ist kein Fehler des Browsers --
|
||||
eine Datei hat keine Gestaltung.
|
||||
|
||||
DER VERWEIS BLEIBT EIN VERWEIS. `target`, `rel` und `href`
|
||||
stehen unveraendert da; mittlere Maustaste, „In neuem Tab
|
||||
oeffnen" und Herunterladen gehen wie seit jeher. Abgefangen
|
||||
wird nur der gewoehnliche Klick -- und auch der nur, wenn die
|
||||
Schau ueberhaupt geladen ist. Faellt die Datei aus, ist man
|
||||
wieder beim alten Verhalten statt bei gar keinem.
|
||||
|
||||
`metaKey`, `ctrlKey`, `shiftKey` UND DIE MITTLERE TASTE sind
|
||||
ausgenommen: Das sind die Griffe, mit denen Leute seit zwanzig
|
||||
Jahren in einem neuen Tab oeffnen. Wer sie abfaengt, nimmt
|
||||
etwas weg, das niemand vermisst -- bis er es braucht. */
|
||||
kasten.addEventListener('click', (e) => {
|
||||
if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
||||
if (!window.Bildschau) return;
|
||||
e.preventDefault();
|
||||
window.Bildschau.zeigen(a, kasten);
|
||||
});
|
||||
|
||||
const bild = document.createElement('img');
|
||||
bild.src = a.weg;
|
||||
bild.alt = a.name || 'Foto';
|
||||
|
||||
Reference in New Issue
Block a user