/** * Die Anzeigegröße der Anwendung – reine Logik, ohne Electron. * * **Warum Zoom und nicht nur Schriftgröße.** Eine reine Schriftvergrößerung * lässt Bilder unberührt. Der Katalog führt siebzehn Prüfzeichen, bei denen das * Bild die Antwort ist – ein Beschusszeichen, ein PTB-Kreis. Wer * größere Schrift braucht, braucht diese Zeichen erst recht größer. Der Zoom * skaliert alles gemeinsam, und das Layout dieser Anwendung ist darauf * ausgelegt: Es fließt um, statt zu brechen. * * **Warum feste Stufen.** Stufenlos wäre schwerer zu treffen und schwerer * anzusagen. Die Leiter deckt den Bereich ab, den WCAG 1.4.4 verlangt * (200 Prozent), reicht bis zu dem, an dem WCAG 1.4.10 misst (400 Prozent), * und lässt darunter Luft für kleinere Anzeigen. * * **Warum sie bis 400 Prozent geht.** 1.4.10 (Reflow) ist an einer Messung * festgemacht: 400 Prozent Vergrößerung auf einem 1280 Pixel breiten Fenster, * also 320 CSS-Pixel Inhaltsbreite. Endete die Leiter bei 200 Prozent, ließe * sich dieser Fall mit Bordmitteln gar nicht herstellen – das Kriterium wäre * nicht erfüllt, sondern nur unprüfbar. Die drei oberen Stufen (250, 300, * 400) sind dieselben, die auch Chromium anbietet; wer sie aus dem Browser * kennt, findet keine fremde Skala vor. */ /** Die wählbaren Anzeigegrößen in Prozent. */ export const ANZEIGEGROESSEN = Object.freeze([ 80, 90, 100, 110, 125, 150, 175, 200, 250, 300, 400, ] as const); export type Anzeigegroesse = (typeof ANZEIGEGROESSEN)[number]; /** Vorgabe: unverändert. */ export const ANZEIGEGROESSE_STANDARD = 100; /** * Bringt einen beliebigen Wert auf eine gültige Stufe. * * Nicht die nächstgelegene, sondern die nächstkleinere gültige Stufe: Wer * einen Wert zwischen zwei Stufen gespeichert hat – etwa aus einer früheren * Fassung –, soll nicht plötzlich größer sehen als vorher. */ export function anzeigegroesseBereinigen(wert: unknown): number { if (typeof wert !== 'number' || !Number.isFinite(wert)) { return ANZEIGEGROESSE_STANDARD; } const kleinste = ANZEIGEGROESSEN[0]; const groesste = ANZEIGEGROESSEN[ANZEIGEGROESSEN.length - 1] ?? ANZEIGEGROESSE_STANDARD; if (wert <= kleinste) { return kleinste; } if (wert >= groesste) { return groesste; } return [...ANZEIGEGROESSEN].reverse().find((stufe) => stufe <= wert) ?? ANZEIGEGROESSE_STANDARD; } /** Eine Stufe größer; an der obersten Stufe bleibt es dabei. */ export function groesser(aktuell: number): number { const jetzt = anzeigegroesseBereinigen(aktuell); return ANZEIGEGROESSEN.find((stufe) => stufe > jetzt) ?? jetzt; } /** Eine Stufe kleiner; an der untersten Stufe bleibt es dabei. */ export function kleiner(aktuell: number): number { const jetzt = anzeigegroesseBereinigen(aktuell); return [...ANZEIGEGROESSEN].reverse().find((stufe) => stufe < jetzt) ?? jetzt; } export function istGroesstmoeglich(wert: number): boolean { return anzeigegroesseBereinigen(wert) === ANZEIGEGROESSEN[ANZEIGEGROESSEN.length - 1]; } export function istKleinstmoeglich(wert: number): boolean { return anzeigegroesseBereinigen(wert) === ANZEIGEGROESSEN[0]; } /** * Chromiums Zoomfaktor zur Prozentangabe. * * `setZoomFactor(1.5)` entspricht 150 Prozent – die Umrechnung ist trivial * und steht trotzdem hier, damit die Prozentzahl die eine Wahrheit bleibt * und niemand an zwei Stellen mit 1,5 gegen 150 hantiert. */ export function zoomfaktor(prozent: number): number { return anzeigegroesseBereinigen(prozent) / 100; } /** „125 Prozent" – für Ansagen und Beschriftungen. */ export function anzeigegroesseText(prozent: number): string { return `${String(anzeigegroesseBereinigen(prozent))} Prozent`; }