Add videos: library, block and section background
Videos join the media library as their own table (schema v28), with a video block and a looping background on sections. video.js starts loops only while visible, offers a pause button and leaves the still image for reduced motion and data saving. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PWYm8kjAWmZaB2QB2xuBhU
This commit is contained in:
1 parent
592e3d5342
commit
76613b9f8e
25 files changed
+674
-20
No files matched your search
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Schleifenvideos: im Hintergrund einer Sektion oder im Video-Baustein.
|
||||
*
|
||||
* Abgespielt wird erst von hier aus, nicht mit autoplay im HTML. So lädt die Seite zuerst ihren
|
||||
* Inhalt, das Video folgt danach (preload="none"), und es läuft nur, solange es zu sehen ist.
|
||||
* Wer „Bewegung reduzieren“ eingestellt hat oder Daten sparen will, bekommt das Standbild und kann
|
||||
* das Video selbst starten. Der Knopf gehört dazu: Bewegung, die länger als fünf Sekunden läuft,
|
||||
* muss sich anhalten lassen (WCAG 2.2.2). Ohne Skript bleibt das Standbild.
|
||||
*/
|
||||
const reduced = matchMedia('(prefers-reduced-motion: reduce)');
|
||||
const saving = navigator.connection?.saveData === true;
|
||||
|
||||
for (const video of document.querySelectorAll('[data-video-loop]')) {
|
||||
const toggle = video.parentElement.querySelector(':scope > .video-toggle');
|
||||
let wanted = !reduced.matches && !saving;
|
||||
let visible = false;
|
||||
const paint = () => {
|
||||
toggle.classList.toggle('is-paused', !wanted);
|
||||
toggle.setAttribute('aria-label', wanted ? toggle.dataset.pause : toggle.dataset.play);
|
||||
};
|
||||
const sync = () => {
|
||||
if (!wanted || !visible) { video.pause(); return; }
|
||||
video.play().catch(error => {
|
||||
// Ein Anhalten mitten im Starten ist kein Fehler. Verweigert der Browser das Abspielen,
|
||||
// etwa im Stromsparmodus, zeigt der Knopf die Wahrheit.
|
||||
if (error.name === 'NotAllowedError') { wanted = false; paint(); }
|
||||
});
|
||||
};
|
||||
toggle.hidden = false;
|
||||
toggle.addEventListener('click', () => { wanted = !wanted; paint(); sync(); });
|
||||
reduced.addEventListener('change', () => { if (reduced.matches) { wanted = false; paint(); sync(); } });
|
||||
new IntersectionObserver(([entry]) => { visible = entry.isIntersecting; sync(); }).observe(video);
|
||||
paint();
|
||||
}
|
||||
Reference in new issue
Block a user