Ein Kreisel ist kein Pausenknopf
Während der Player auf Daten wartete, stand im mittleren Knopf das Abspieldreieck und der Ladekreis lag dahinter. Das las sich als „angehalten": man drückte auf Abspielen, und es geschah nichts — es lief ja bereits, es kam nur nichts an. Jetzt sitzt der Kreisel **im** Knopf, dort wo sonst das Symbol steht. Der freistehende Kreisel in der Bildmitte bleibt für den Fall, dass die Bedienelemente ausgeblendet sind. Zwei übereinander gibt es nicht mehr. `togglePlayPause` zählt das Warten jetzt zum Laufen. Vorher führte ein Tipp in diesem Moment zu `play()` auf etwas, das schon spielte. Dazu auf dem Mac, wie im Browser auch: - Ein Klick ins Bild hält an, statt erst die Bedienelemente zu holen. Die kommen dort von allein, sobald sich der Zeiger regt. - Leertaste hält an, Pfeil links und rechts springen. Mit dem Finger bleibt es beim Alten: ohne Zeiger gibt es keine Bewegung ohne Berührung, und ein Tipp, der sofort anhält, nähme den einzigen Weg zu Scrubber, Tonspur und Qualität. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
3af6c3112f
commit
9a4b6b1e06
+11
-2
@@ -341,19 +341,28 @@ img { display: block; }
|
||||
|
||||
/* Während geladen wird, treten die Transportknöpfe zurück: sie tun ohnehin
|
||||
nichts, und der Kreisel lag vorher genau hinter dem größten von ihnen. */
|
||||
#player.loading .pl-center { opacity: 0; pointer-events: none; }
|
||||
/* Während des ersten Ladens haben Vor- und Zurückspulen keine Wirkung — es
|
||||
gibt noch keine Zeitachse. Der mittlere Knopf bleibt stehen: er trägt
|
||||
jetzt selbst den Kreisel. */
|
||||
#player.loading .pl-center > :not(.pl-play) { opacity: 0; pointer-events: none; }
|
||||
.pl-center { transition: opacity .2s ease; }
|
||||
|
||||
.pl-busy {
|
||||
position: absolute; display: none; pointer-events: none;
|
||||
}
|
||||
.pl-busy.on { display: block; }
|
||||
.pl-busy i {
|
||||
.pl-busy i, .pl-wait {
|
||||
display: block; width: 44px; height: 44px; border-radius: 999px;
|
||||
border: 3px solid rgba(255,255,255,.2); border-top-color: var(--accent);
|
||||
animation: spin .8s linear infinite;
|
||||
}
|
||||
|
||||
/* Feste Größe für den mittleren Knopf, damit die beiden daneben stehen
|
||||
bleiben: der Kreisel ist schmaler als das Symbol, das er vertritt, und
|
||||
ohne diese Zeile rückten Zurück- und Vorspulen bei jedem Wechsel
|
||||
zusammen. */
|
||||
.pl-round.pl-play { width: 68px; height: 68px; }
|
||||
|
||||
.pl-error {
|
||||
position: absolute; max-width: 460px; padding: var(--s-section);
|
||||
background: var(--elevated); border: 1px solid rgba(229,72,77,.35);
|
||||
|
||||
+42
-10
@@ -76,10 +76,16 @@ export function playerOeffnen(item: Item, beimSchliessen?: () => void): void {
|
||||
|
||||
/* ---------- Fehler sichtbar machen ---------- */
|
||||
let hls: HlsTyp | null = null;
|
||||
/** Ob gerade auf Daten gewartet wird — am Anfang immer. */
|
||||
let wartet = true;
|
||||
|
||||
const scheitern = (satz: string, hinweis?: string, adresse?: string): void => {
|
||||
ebene.classList.remove('loading');
|
||||
el('pl-busy').classList.remove('on');
|
||||
// Sonst dreht sich der Kreisel im Knopf hinter dem Fehlerkasten weiter,
|
||||
// als käme noch etwas.
|
||||
wartet = false;
|
||||
malen();
|
||||
ebene.querySelector('.pl-error')?.remove();
|
||||
const kasten = document.createElement('div');
|
||||
kasten.className = 'pl-error';
|
||||
@@ -105,7 +111,21 @@ export function playerOeffnen(item: Item, beimSchliessen?: () => void): void {
|
||||
clearTimeout(ausblenden);
|
||||
// Solange etwas steht, bleibt die Bedienung: sie auszublenden, während
|
||||
// niemand spielt, versteckt den einzigen Knopf, der weiterhilft.
|
||||
if (!v.paused) ausblenden = setTimeout(() => chrome.classList.remove('on'), 3000);
|
||||
if (!v.paused) {
|
||||
ausblenden = setTimeout(() => {
|
||||
chrome.classList.remove('on');
|
||||
kreisel();
|
||||
}, 3000);
|
||||
}
|
||||
kreisel();
|
||||
};
|
||||
|
||||
/** Der freistehende Kreisel — nur, wenn die Bedienung aus ist.
|
||||
*
|
||||
* Sonst stünden zwei übereinander: einer in der Mitte des Bildes und einer
|
||||
* im Abspielknopf, der genau davor sitzt. Genau so sah es vorher aus. */
|
||||
const kreisel = (): void => {
|
||||
el('pl-busy').classList.toggle('on', wartet && !chrome.classList.contains('on'));
|
||||
};
|
||||
ebene.addEventListener('mousemove', zeigen);
|
||||
ebene.addEventListener('touchstart', zeigen, { passive: true });
|
||||
@@ -117,16 +137,28 @@ export function playerOeffnen(item: Item, beimSchliessen?: () => void): void {
|
||||
el('pl-fwd').onclick = () => { v.currentTime = Math.min(v.duration || 1e9, v.currentTime + P.skipForward); zeigen(); };
|
||||
v.addEventListener('click', umschalten);
|
||||
|
||||
/** Zeichnet den mittleren Knopf: Kreisel, Dreieck oder Doppelbalken.
|
||||
*
|
||||
* Solange auf Daten gewartet wird, steht dort der Kreisel — **kein**
|
||||
* Dreieck. Ein Dreieck heißt „angehalten, drück mich", und beides stimmte
|
||||
* nicht: es lief bereits, und der Klick bewirkte nichts. */
|
||||
const malen = (): void => {
|
||||
el('pl-toggle').innerHTML = icon(v.paused ? 'play' : 'pause', 52);
|
||||
el('pl-toggle').setAttribute('aria-label', v.paused ? 'Abspielen' : 'Anhalten');
|
||||
zeigen();
|
||||
const knopf = el('pl-toggle');
|
||||
knopf.innerHTML = wartet ? '<i class="pl-wait"></i>' : icon(v.paused ? 'play' : 'pause', 52);
|
||||
knopf.setAttribute('aria-label', wartet ? 'Lädt' : v.paused ? 'Abspielen' : 'Anhalten');
|
||||
};
|
||||
v.addEventListener('play', malen);
|
||||
v.addEventListener('pause', malen);
|
||||
v.addEventListener('waiting', () => el('pl-busy').classList.add('on'));
|
||||
|
||||
const warten = (an: boolean): void => {
|
||||
wartet = an;
|
||||
malen();
|
||||
kreisel();
|
||||
};
|
||||
|
||||
v.addEventListener('play', () => { malen(); zeigen(); });
|
||||
v.addEventListener('pause', () => { warten(false); zeigen(); });
|
||||
v.addEventListener('waiting', () => warten(true));
|
||||
v.addEventListener('playing', () => {
|
||||
el('pl-busy').classList.remove('on');
|
||||
warten(false);
|
||||
ebene.classList.remove('loading');
|
||||
});
|
||||
|
||||
@@ -202,7 +234,7 @@ export function playerOeffnen(item: Item, beimSchliessen?: () => void): void {
|
||||
lauf.stelle = v.currentTime || 0;
|
||||
ebene.querySelector('.pl-error')?.remove();
|
||||
ebene.classList.add('loading');
|
||||
el('pl-busy').classList.add('on');
|
||||
warten(true);
|
||||
menueZu();
|
||||
void strom();
|
||||
};
|
||||
@@ -411,7 +443,7 @@ export function playerOeffnen(item: Item, beimSchliessen?: () => void): void {
|
||||
zeigen();
|
||||
tonMalen();
|
||||
ebene.classList.add('loading');
|
||||
el('pl-busy').classList.add('on');
|
||||
warten(true);
|
||||
void strom();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user