Im vorherigen Cross Browser Video Player Artikel haben wir beschrieben, wie ein plattformübergreifender HTML-Videoplayer mit den Media- und Vollbild-APIs erstellt wird. Dieser Folgeartikel behandelt, wie dieser benutzerdefinierte Player stilisiert und responsiv gemacht werden kann.
Es wurden einige Änderungen am HTML-Markup vorgenommen, das im vorherigen Artikel gezeigt wurde. Die benutzerdefinierten Videosteuerungen und das <progress>-Element befinden sich jetzt in <div>-Elementen, anstatt in Elementen einer ungeordneten Liste.
Das Markup für die benutzerdefinierten Steuerungen sieht nun wie folgt aus:
Ein data-state-Attribut wird an verschiedenen Stellen für Styling-Zwecke verwendet und diese werden mit JavaScript gesetzt. Spezifische Implementierungen werden an geeigneten Stellen unten erwähnt.
Der resultierende Stil des Videoplayers, der hier verwendet wird, ist eher einfach — das ist beabsichtigt, da es darum geht, zu zeigen, wie ein solcher Videoplayer gestaltet und responsiv gemacht werden kann.
Hinweis:
In einigen Fällen wird hier auf einige grundlegende CSS-Beispiele verzichtet, da deren Verwendung entweder offensichtlich oder nicht speziell relevant für das Styling des Videoplayers ist.
Die Position wird auf relative gesetzt, was für seine Responsivität erforderlich ist (dazu später mehr).
Wie bereits erwähnt, wird ein data-state-Attribut verwendet, um anzuzeigen, ob die Videosteuerungen sichtbar sind oder nicht, und es benötigt entsprechende CSS-Deklarationen:
Jede Schaltfläche hat eine Breite und Höhe von 2rem. Standardmäßig haben alle <button>-Elemente einen Rahmen, daher wird dieser entfernt. Da Hintergrundbilder verwendet werden, um geeignete Symbole anzuzeigen, wird die Hintergrundfarbe der Schaltfläche auf transparent gesetzt, nicht wiederholt und das Element soll das Bild vollständig enthalten. Darüber hinaus gibt es etwas Beschriftungstext, der auf dem Bildschirm nicht sichtbar sein soll, daher wird die Textfarbe auf transparent gesetzt.
Die :hover- und :focus-Zustände werden dann für jede Schaltfläche eingestellt, die die Deckkraft der Schaltfläche ändert:
Um geeignete Schaltflächenbilder zu erhalten, wurde ein Satz von kostenlosen, häufig verwendeten Steuerelement-Symbolen aus dem Internet heruntergeladen. Jedes Bild wurde dann in einen Base64-kodierten String konvertiert (mithilfe eines Online-Base64 Image Encoder), da die Bilder recht klein sind, sind die resultierenden kodierten Strings ziemlich kurz.
Da einige Schaltflächen eine doppelte Funktionalität haben, z. B. Abspielen/Pause und Stumm/Unstumm, haben diese Schaltflächen unterschiedliche Zustände, die gestylt werden müssen. Wie bereits erwähnt, wird eine data-state-Variable verwendet, um anzuzeigen, in welchem Zustand sich solche Schaltflächen gerade befinden.
Zum Beispiel hat die Abspielen/Pause-Schaltfläche die folgenden Hintergrundbilddefinitionen (die vollständigen Base64-Strings wurden aus Gründen der Kürze weggelassen):
Der <div>-Container für das <progress>-Element hat sein flex-grow aktiviert, sodass er den verbleibenden Raum in den Steuerungen ausfüllt. Es zeigt auch einen Zeiger-Cursor an, um anzuzeigen, dass es interaktiv ist.
Wie die <button>-Elemente hat auch das <progress>-Element einen Standardrahmen, der hier entfernt wird. Es erhält auch eine leicht abgerundete Ecke aus ästhetischen Gründen.
Es gibt einige browserspezifische Eigenschaften, die festgelegt werden müssen, um sicherzustellen, dass Firefox und Chrome die erforderliche Farbe für den Fortschrittsbalken verwenden:
Obwohl die gleichen Eigenschaften auf den gleichen Wert eingestellt sind, müssen diese Regeln separat definiert werden, da die gesamte Deklaration möglicherweise nicht gültig wird, wenn ein Selektor nicht erkannt wird.
Nun gestalten wir die Steuerungen für den Vollbildmodus. Da das <figure>-Element das Element ist, das im Vollbildmodus angezeigt wird, können wir es mit der :fullscreen-Pseudoklasse ansprechen. Wir machen Folgendes:
Lassen Sie die figure den gesamten Bildschirm mit height: 100% einnehmen
Lassen Sie die Steuerleiste unten haften, während das Video zentriert bleibt, verwendet wird Flexbox
Machen Sie den Container transparent, um die native Hintergrundfarbe anzuzeigen
Verbergen Sie das figcaption
Stellen Sie die Hintergrundfarbe für die Steuerungsreihe wieder her, um sicherzustellen, dass unsere schwarzen Schaltflächen weiterhin sichtbar sind, wenn der Hintergrund schwarz ist.
Jetzt, da der Player sein grundlegendes Aussehen und Gefühl bekommen hat, müssen einige andere Stiländerungen — unter Verwendung von Media Queries — vorgenommen werden, um ihn responsiv zu machen.
Wir möchten das Layout der Steuerungen anpassen, wenn es auf einem kleineren Bildschirm (680px/42.5em) angezeigt wird, daher wird hier ein Breakpoint definiert. Wir ändern die Größen- und Positions-Eigenschaften für die Schaltflächen und den Fortschrittsbalken, sodass sie anders angeordnet sind:
Der .progress-Container wird jetzt über position:absolute an die Spitze des Steuerungssatzes verschoben, also müssen er und alle Schaltflächen breiter werden. Darüber hinaus müssen die Schaltflächen unter den Fortschrittscontainer geschoben werden, damit sie sichtbar sind.
Das ist wirklich alles für das direkte Styling; die nächste Aufgabe besteht darin, eine Anzahl von JavaScript-Änderungen vorzunehmen, um sicherzustellen, dass alles wie erwartet funktioniert, hauptsächlich um die Logik der Schaltflächen neu zu gestalten.
const videoContainer = document.getElementById("videoContainer");
const video = document.getElementById("video");
const videoControls = document.getElementById("video-controls");
const playPause = document.getElementById("play-pause");
const stop = document.getElementById("stop");
const mute = document.getElementById("mute");
const volInc = document.getElementById("vol-inc");
const volDec = document.getElementById("vol-dec");
const progress = document.getElementById("progress");
const fullscreen = document.getElementById("fs");
// Hide the default controls
video.controls = false;
// Display the user defined video controls
videoControls.setAttribute("data-state", "visible");
Nachdem die Schaltflächen nun tatsächlich wie Schaltflächen aussehen und Bilder haben, die anzeigen, was sie tun, müssen einige Änderungen vorgenommen werden, damit die "doppelten Funktionen" (wie z.B. die Abspielen/Pause-Schaltfläche) im richtigen "Zustand" sind und das richtige Bild anzeigen. Um dies zu erleichtern, wird eine neue Funktion namens changeButtonState() definiert, die einen Typ-Parameter akzeptiert, der die Funktion der Schaltfläche angibt:
Diese Funktion wird dann von den entsprechenden Ereignishandlern aufgerufen:
js
video.addEventListener("play", () => {
changeButtonState("play-pause");
});
video.addEventListener("pause", () => {
changeButtonState("play-pause");
});
stop.addEventListener("click", (e) => {
video.pause();
video.currentTime = 0;
progress.value = 0;
// Update the play/pause button's 'data-state' which allows the
// correct button image to be set via CSS
changeButtonState("play-pause");
});
mute.addEventListener("click", (e) => {
video.muted = !video.muted;
changeButtonState("mute");
});
Vielleicht haben Sie bemerkt, dass es neue Handler gibt, bei denen auf die play- und pause-Ereignisse des Videos reagiert wird. Dafür gibt es einen Grund! Auch wenn die standardmäßigen Videosteuerungen des Browsers ausgeschaltet sind, machen viele Browser sie über einen Rechtsklick auf das HTML-Video zugänglich. Dies bedeutet, dass ein Benutzer das Video über diese Steuerungen abspielen/pausieren könnte, was dann dazu führen würde, dass die Schaltflächen des benutzerdefinierten Steuerungssatzes nicht synchron sind. Wenn ein Benutzer die Standardsteuerungen verwendet, werden die definierten Media-API-Ereignisse — wie play und pause — ausgelöst, sodass dies genutzt werden kann, um sicherzustellen, dass die benutzerdefinierten Steuerschaltflächen synchron gehalten werden. Unser Klick löst ebenfalls die play- und pause-Ereignisse aus, wenn die play()- und pause()-Methoden aufgerufen werden, sodass sich hier nichts ändern muss:
Die Funktion alterVolume(), die aufgerufen wird, wenn die Lautstärketasten des Players angeklickt werden, ändert sich ebenfalls — sie ruft jetzt eine neue Funktion namens checkVolume() auf:
js
function checkVolume(dir) {
if (dir) {
const currentVolume = Math.floor(video.volume * 10) / 10;
if (dir === "+" && currentVolume < 1) {
video.volume += 0.1;
} else if (dir === "-" && currentVolume > 0) {
video.volume -= 0.1;
}
// If the volume has been turned off, also set it as muted
// Note: can only do this with the custom control set as when the 'volumechange' event is raised,
// there is no way to know if it was via a volume or a mute change
video.muted = currentVolume <= 0;
}
changeButtonState("mute");
}
function alterVolume(dir) {
checkVolume(dir);
}
volInc.addEventListener("click", (e) => {
alterVolume("+");
});
volDec.addEventListener("click", (e) => {
alterVolume("-");
});
Diese neue Funktion checkVolume() tut dasselbe wie alterVolume(), allerdings setzt sie den Zustand der Stummschalttaste abhängig von der aktuellen Lautstärkeeinstellung des Videos. checkVolume() wird auch aufgerufen, wenn das volumechange-Ereignis ausgelöst wird: