Anche se l'idea di un elemento HTML specifico per il video è stata suggerita oltre un decennio fa, stiamo solo iniziando a vedere questo risultato! Dimentica tutto questo "HTML5 2012" mumbo-jumbo; la verità è che puoi usare il video
elemento nei tuoi progetti adesso! Devi solo essere a conoscenza di una manciata di requisiti prima di fare il grande passo.
document.createElement ( 'video')
. Stranamente, questo sembra innescare la consapevolezza di IE. Sì, è piuttosto strano, ma ci si aspetta che da Internet Explorer, giusto? Per accelerare questo processo, Remy Sharp ha creato HTML5 Shiv, che inoltre, per inciso, risolve alcuni problemi di stampa quando si lavora con elementi HTML5. Basta scaricare lo script e farne riferimento all'interno di capo
sezione dei tuoi documenti.ogg
formato, mentre i browser Webkit possono eseguire il rendering mp4
video. In realtà, questa è una semplificazione eccessiva; tuttavia, questo lo farà per il momento. Tuttavia, basti dire che sono supportati più tipi di video, incluso il codec V8 di Google di recente apertura. Come in ogni progetto, il nostro primo passo è creare il mark-up necessario per il nostro progetto.
Lettore video HTML5 personalizzato Video HTML5
Innanzitutto, trova alcuni video di esempio con cui lavorare. Il video "Big Bunny Buck" open-source come Pixar è quello che userò. Sono sicuro che lo hai già visto in giro per il web. La visualizzazione di questo markup nel browser potrebbe lasciare un punto interrogativo sopra la tua testa.
Eh? Questo è tutto? Sembra solo un'immagine. Qual è il problema? Bene, per impostazione predefinita, questo è tutto ciò che abbiamo richiesto. Dobbiamo quindi specificare se mostrare o meno i controlli, visualizzare un poster, ecc. Facciamolo ora; rivedi il tuo video
elemento, così:
Subito, notiamo che non ci sono quotazioni attorno agli attributi. A quanto pare, non sono necessari. Mentre anni fa era considerata una cattiva pratica escluderli, non è più così. A questo punto, si riduce solo alle preferenze personali. Quindi, se ti senti più a tuo agio ad aggiungerli, allora, con tutti i mezzi, fallo.
Ovviamente non sappiamo come usare i controlli predefiniti del browser. Come tale, dobbiamo implementare i nostri controlli-mark-up. Prima di progredire, potrebbe esserti chiesto: "Allora qual è il punto di aggiungere il controlli
attributo a tutti? La risposta è perché dobbiamo considerare e compensare il fatto che JavaScript potrebbe essere disabilitato sul computer del visualizzatore. In quei casi, se non avessimo aggiunto il controlli
attributo, vedrebbero solo ciò che sembra essere un'immagine.
Considera sempre la possibilità che JavaScript possa essere disabilitato.
Il div
con un id di "videoControls" è dove aggiungeremo i pulsanti e il logo necessari. Un piccolo trucchetto è l'uso di "& # x25BA;" per creare il pulsante di riproduzione. Non preoccuparti troppo del div "progresso"; esamineremo questa sezione in modo più dettagliato più avanti in questo tutorial. La risposta breve è che questo è il contenitore per la nostra barra di avanzamento. Infine, aggiungiamo a pulsante
che alterna la funzionalità a schermo intero, nonché il logo Tuts +.
Non preoccuparti; anche se sembra che ora abbiamo creato un secondo set di controlli (e senza uno stile), alla fine rimuoveremo i controlli predefiniti con JavaScript. Tuttavia, lo screenshot qui sopra dovrebbe corrispondere alla tua anteprima, se stai seguendo.
Con il mark-up completo, possiamo ora passare alla parte divertente! Crea una nuova cartella, chiamata "js" e aggiungi un nuovo file: videoPlayer.js
. Quindi, diventiamo bravi ragazzi e ragazze e avvolgiamo il nostro codice all'interno di una funzione anonima autoinvitante, per impedire la creazione di variabili globali inutili.
(funzione (finestra, documento) (questo, documento))
Puoi eliminare gli argomenti se lo desideri, è un piccolo miglioramento con due vantaggi:
Questo
(l'oggetto Window globale) e documento
, impediamo al motore JavaScript di dover filtrare e rintracciare quegli oggetti. Questo può essere una grande comodità per i progetti più grandi, ma offre un vantaggio di prestazioni molto piccolo. finestra
e documento
ora può essere rappresentato tramite qualcosa di simile un
e B
. Quindi, continuiamo a mantenere il nostro codice il più pulito possibile creando un lettore video
oggetto che conterrà tutti i nostri metodi. Creeremo anche un dentro
metodo che verrà chiamato immediatamente al caricamento della pagina.
(function (window, document) var videoPlayer = init: function () ; videoPlayer.init (); (this, document))
Poiché certamente manipoleremo elementi nella pagina, andiamo avanti e facciamo riferimento alla loro posizione all'interno delle variabili. Poco prima che dichiariamo la variabile "videoPlayer", anteponiamo:
var video = document.getElementsByTagName ('video') [0], videoControls = document.getElementById ('videoControls'), play = document.getElementById ('play'), progressContainer = document.getElementById ("progress"), progressHolder = document.getElementById ("progress_box"), playProgressBar = document.getElementById ("play_progress"), fullScreenToggleButton = document.getElementById ("fullScreen");
Se stai lavorando (e spero che lo sia), prenditi un po 'di tempo per imparare esattamente ciò che queste variabili fanno riferimento. Rivolgiti al tuo mark-up, se necessario. Prendiamo l'elemento video, i controlli video div, il pulsante play, il pulsante di commutazione a schermo intero e i tre div progressivi. "Memorizziamo" la posizione di questi elementi perché non c'è motivo di percorrere inutilmente il DOM ogni volta che è necessario accedere a uno di questi elementi!
Dentro
Metodo Iniziamo a scrivere un codice reale. All'interno del dentro
metodo, incolla il seguente snippet:
init: function () // questo è uguale all'oggetto videoPlayer. var that = this; // Trigger CSS utile per JS. document.documentElement.className = 'js'; // Elimina i controlli predefiniti, perché useremo il nostro. video.removeAttribute ( 'controlli'); // Quando i metadati sono pronti, mostra i controlli video.addEventListener ('loadeddata', this.initializeControls, false);
Un modo pulito in cui modifichiamo gli elementi in base al fatto che JavaScript sia abilitato consiste nell'applicare una classe di "js" a documentElement
, o il html
elemento.
// Trigger CSS utile per JS. document.documentElement.className = 'js';
Questo ci permette di scrivere CSS come:
.js #container / * questo styling esegue il rendering solo se JS è abilitato * /
Ricorda il problema con i due set di controlli video? Rimediamolo adesso. Questo è facile; useremo semplicemente il removeAttribute
metodo, e sbarazzarsi di controlli
.
// Elimina i controlli predefiniti, perché useremo il nostro. video.removeAttribute ( 'controlli');
Aggiungiamo ora il nostro primo evento HTML5: loadeddata
. Questo evento si attiva quando il browser ha finito di caricare i metadati per il video. Questo è un punto eccellente per eseguire qualsiasi procedura iniziale, come la visualizzazione di controlli personalizzati.
// Quando i metadati sono pronti, mostra i controlli video.addEventListener ('loadeddata', this.initializeControls, false);
Se conosci un po 'di JavaScript, potresti essere preoccupato che non stiamo indennizzando Internet Explorer. Per quelli inconsapevoli, IE8 e seguenti non riconoscono addEventListener
. Invece, nel modo in cui si è abituato, IE usa il suo attachEvent
. Tuttavia, è tutto cambiato nella versione nove del browser. Come IE8 e sotto non capisco il video
elemento, possiamo ignorare il attachEvent
evento interamente.
Quando il loadeddata
gli incendi degli eventi, chiamiamo il metodo "initializeControls" che deve ancora essere creato. All'interno di un metodo oggetto, non possiamo riferirci a "initializeControls" da solo. Dobbiamo prima fare riferimento all'oggetto stesso: quindi, this.initializeControls
.
Andiamo avanti e creare questo metodo ora.
initializeControls: function () // Quando tutte le meta informazioni sono caricate, mostra i controlli videoPlayer.showHideControls ();
Come accennato in precedenza, se si scrive il proprio player personalizzato, utilizzare questo metodo per eseguire eventuali procedure iniziali aggiuntive. Per ora, questo metodo chiamerà un altro metodo, showHideControls
. Questo nuovo metodo mostrerà o nasconderà i controlli quando l'utente si posiziona sul video.
showHideControls: function () // Mostra e nasconde il video player. video.addEventListener ('mouseover', function () videoControls.style.opacity = 1;, false); videoControls.addEventListener ('mouseover', function () videoControls.style.opacity = 1;, false); video.addEventListener ('mouseout', function () videoControls.style.opacity = 0;, false); videoControls.addEventListener ('mouseout', function () videoControls.style.opacity = 0;, false);
Questo metodo collega quattro gestori di eventi al video player e controlla gli elementi, rappresentati da video
e videoControls
variabili, rispettivamente. Questo codice è semplice: quando passi il mouse sul video, modifica l'opacità dei controlli video su 1. Inversamente, quando tieni il mouse fuori, nascondi i controlli dalla vista. Questo codice presuppone anche che, di default, all'interno del nostro foglio di stile, il controllo del video opacità
è impostato su none.
Ricorda: quando possibile, delegare sempre lo stile al nostro file CSS, piuttosto che aggiungerlo direttamente con il tuo JavaScript. Oltre ai vantaggi prestazionali e alla riduzione di reflows / repaints, questa pratica aderisce correttamente alla separazione della presentazione dalla logica. Tuttavia, di tanto in tanto, non avrai altra scelta che aggiungere lo stile nel tuo file JavaScript e, in quei casi, va bene.
Ora abbiamo nascosto con successo i controlli predefiniti, ma non abbiamo ancora applicato alcuna logica a questi pulsanti personalizzati. Questo è quello che dobbiamo fare dopo.
Ritorna al dentro
metodo e aggiungere una chiamata a un nuovo metodo.
// Durante la riproduzione, i pulsanti di pausa vengono premuti. this.handleButtonPresses ();
Ovviamente sei libero di chiamare questi metodi come desideri, ma almeno prova a nominarli in modo tale che sia facile capire esattamente quale sia lo scopo della funzione.
handleButtonPresses: function () // Quando si fa clic sul pulsante video o play, riprodurre / mettere in pausa il video. video.addEventListener ('click', this.playPause, false); play.addEventListener ('click', this.playPause, false); // Quando viene premuto il pulsante di riproduzione, // passa al simbolo "Pausa". video.addEventListener ('play', function () play.title = 'Pause'; play.innerHTML = '& # X2590; & # x2590;'; , falso); // Quando viene premuto il pulsante di pausa, // passa al simbolo "Riproduci". video.addEventListener ('pause', function () play.title = 'Play'; play.innerHTML = '& # x25BA;';, false); // Al termine del video, mettilo in pausa. video.addEventListener ('ended', function () this.currentTime = 0; this.pause ();, false);
All'interno di questo metodo, aggiungiamo di nuovo una manciata di nuovi eventi disponibili per video
elemento: giocare
, pausa
, e conclusa
.
Tieni presente che, ad esempio, il
giocare
l'evento non si attiva quando si fa clic sul pulsante di riproduzione che abbiamo creato. No, invece, si attiva quando il video stesso inizia a suonare. Questa è una distinzione importante da ricordare.
Per attivare gli eventi elencati sopra, aggiungiamo un altro listener di eventi al pulsante di riproduzione e ascoltiamo quando l'utente fa clic su di esso.
// Quando si fa clic sul pulsante del video o di riproduzione, riprodurre / mettere in pausa il video. play.addEventListener ('click', this.playPause, false);
playPause: function () if (video.paused || video.ended) if (video.ended) video.currentTime = 0; video.play (); else video.pause ();
Parliamo del codice sopra in generale. Quando è stato chiamato questo metodo - nel nostro caso, quando viene cliccato per primo il pulsante play - è stato messo in pausa o alla fine del video? In quest'ultimo caso, è necessario reimpostare l'ora del video su 0, in modo che possa essere riprodotta dall'inizio. Quindi, dobbiamo riprodurre il video: video.play ()
.
Ora se il video non è stato messo in pausa o alla fine - il che significa che il video era in fase di riproduzione quando è stato fatto clic sul pulsante di riproduzione, dovremmo fare il contrario e mettere in pausa il video: Video.pause ()
.
Il play pausa
metodo, dettagliato sopra, gestisce il processo di riproduzione o sospensione del video. Ma dobbiamo certamente fornire all'utente un feedback su cosa fa il pulsante push, giusto? Decisamente; per farlo, passeremo da un codice di carattere HTML "play" e "pause" ogni volta che si fa clic sul pulsante. Quindi, essenzialmente, questo pulsante gestisce sia la riproduzione che la pausa.
Se farai riferimento agli ascoltatori di eventi di un momento fa, abbiamo già aggiunto questa funzionalità.
// Quando viene premuto il pulsante di riproduzione, // passa al simbolo "Pausa". video.addEventListener ('play', function () play.title = 'Pause'; play.innerHTML = '& # X2590; & # x2590;'; , falso); // Quando viene premuto il pulsante di pausa, // passa al simbolo "Riproduci". video.addEventListener ('pause', function () play.title = 'Play'; play.innerHTML = '& # x25BA;';, false);
Abbastanza semplice, vero? Se viene premuto il pulsante di riproduzione, il clic
l'evento del pulsante di riproduzione si attiva, che chiama video.play ()
. Questo metodo quindi riproduce il video e attiva il giocare
evento. Il giocare
l'evento cambia quindi il valore del pulsante in un simbolo di pausa e aggiorna anche l'attributo titolo. Infine, quando questo processo si ripresenta, facciamo l'opposto.
L'ho menzionato nel paragrafo iniziale di questo tutorial: il supporto a schermo intero è un must per me. Aggiungiamo ora quella funzionalità. Torna al tuo dentro()
metodo, e, ancora, aggiungere uno snippet in fondo. Abbiamo bisogno di ascoltare quando quel pulsante di commutazione a schermo intero che abbiamo creato ...
... viene cliccato. Quando lo è, dovremmo cambiare il video a schermo intero, o il contrario.
Non dimenticare:
fullScreenToggleButton
si riferisce al pulsante "fullScreen".
// Quando viene premuto il pulsante a schermo intero ... fullScreenToggleButton.addEventListener ("click", function () isVideoFullScreen? That.fullScreenOff (): that.fullScreenOn ();, true);
Aspetta un attimo: cos'è quello
? Non dovrebbe essere Questo
? La risposta è no. Nel contesto dell'evento click, Questo
ora si riferisce al pulsante "fullScreen", non al lettore video
oggetto.
Per rimediare, "memorizzeremo" il valore originale di Questo
all'interno di una variabile, chiamato quello
. Questo può essere aggiunto al top del nostro dentro()
metodo.
init: function () // questo è uguale all'oggetto videoPlayer. var that = this; ...
Ta da! Ora, possiamo nuovamente fare riferimento al lettore video
oggetto. Come tale, that.fullScreenOff
significa "accedi al metodo chiamato" fullScreenOff "che è figlio di lettore video
oggetto.
C'è un problema Come determiniamo lo stato attuale del video? È a grandezza naturale o normale? Un modo semplice per gestire questa situazione è creare una variabile, chiamata "isVideoFullScreen." Puoi aggiungere questa variabile nella parte superiore della pagina, insieme alle altre. Per impostazione predefinita, ovviamente, questo valore deve essere impostato su falso
.
fullScreenToggleButton = document.getElementById ("fullScreen"), // Boolean che ci consente di "ricordare" la dimensione corrente del video player. isVideoFullScreen = false,
Questo booleano ora ci consente di chiamare correttamente la funzione appropriata quando viene cliccato il pulsante "fullScreen".
isVideoFullScreen? that.fullScreenOff (): that.fullScreenOn ();
Usando l'operatore ternario, controlliamo: "il video è attualmente in modalità a schermo intero? Se lo è, chiamiamo fullScreenOff ()
. Altrimenti, chiamiamo fullScreenOn ()
.
fullScreenOn: function () isVideoFullScreen = true; // Imposta una nuova larghezza in base alla larghezza della finestra video.style.cssText = 'position: fixed; larghezza: '+ window.innerWidth +' px; altezza: '+ window.innerHeight +' px; '; // Applica un nome di classe al video e controlla, se il designer ne ha bisogno ... video.className = 'fullsizeVideo'; videoControls.className = 'fs-control'; fullScreenToggleButton.className = "controllo fs-active"; // Ascolta la chiave di escape. Se premuto, chiude a schermo intero. document.addEventListener ('keydown', this.checkKeyCode, false); , fullScreenOff: function () isVideoFullScreen = false; video.style.position = 'static'; video.className = "; fullScreenToggleButton.className =" control "; videoControls.className =";
All'interno di queste due funzioni, prima cambiamo il valore di isVideoFullScreen
, di conseguenza. Successivamente, regoliamo le dimensioni del video stesso. cssText
ci consente di passare una stringa di stile a un elemento. In questo caso, non possiamo eseguire questo compito direttamente dal nostro foglio di stile. Questo perché i valori desiderati sono dinamici e dipenderanno dalle dimensioni della finestra del browser del visitatore.
Uso
window.innerWidth
ewindow.innerHeight
per recuperare la larghezza e l'altezza della finestra del browser.
È anche una buona pratica applicare nomi di classe specifici per tutti i nostri elementi. In questo modo, se hai bisogno di aggiungere uno stile appropriato, ora hai un nome di classe da agganciare.
Oltre al pulsante di attivazione a schermo intero, è anche abbastanza comune lasciare la modalità a schermo intero quando l'utente preme il tasto Esc sulla tastiera. È una buona comodità, ed è una cosa che dovremmo implementare nel nostro lettore. Fortunatamente, è facile!
// Ascolta la chiave di escape. Se premuto, chiude a schermo intero. document.addEventListener ('keydown', this.checkKeyCode, false);
Per ascoltare i clic chiave, usiamo il keydown
evento. Mentre potrei passare una funzione anonima come secondo parametro, questo bit di codice potrebbe essere utilizzato in più punti. E quando questo è vero, il codice dovrebbe essere trasferito alla sua funzione, per il riutilizzo. Lo chiameremo, checkKeyCode
.
// Determina se è stato premuto il tasto Esc. checkKeyCode: function (e) e = e || window.event; if ((e.keyCode || e.which) === 27) videoPlayer.fullScreenOff ();
Questa funzione è purtroppo più confusa di quanto dovrebbe essere, a causa di problemi di Internet Explorer. Non sono certo che il prossimo IE9 gestisca l'oggetto evento, quindi, per il momento, compenseremo comunque le discrepanze tra il modo in cui IE e gli altri browser moderni gestiscono l'oggetto evento.
Cose noiose a parte, questo codice controlla se la chiave su cui è stato fatto clic ha un codice di "27". Se lo fa, quindi il tasto "Escape" è stato premuto, nel qual caso possiamo uscire a schermo intero, via videoPlayer.fullScreenOff ()
.
Ultimo, ma non meno importante, dobbiamo monitorare lo stato del video. Quindi, man mano che il video procede, dobbiamo fornire uno "scrubber" di avanzamento che aiuti a tracciare il video. Consente inoltre all'utente di eseguire rapidamente la scansione nella parte desiderata del video.
È facile: quando il video è in riproduzione! Quindi, con questo in mente, modifichiamo il nostro giocare
codice evento e chiama una funzione che traccerà i progressi del video.
// Quando viene premuto il pulsante di riproduzione, // passa al simbolo "Pausa". video.addEventListener ('play', function () play.title = 'Pause'; play.innerHTML = '& # X2590; & # x2590;'; // Inizia a monitorare i progressi del video. videoPlayer.trackPlayProgress (); , falso);
// Ogni 50 millisecondi, aggiorna i progressi del gioco. trackPlayProgress: function () (function progressTrack () videoPlayer.updatePlayProgress (); playProgressInterval = setTimeout (progressTrack, 50);) ();
Non lasciare che questo codice ti spaventi. È semplicemente una funzione ricorsiva che ci consente di chiamare un metodo diverso, updatePlayProgress ()
, ogni cinquanta millisecondi. Perché non usare setInterval
anziché? Questo è perché setInterval
può essere cattivo a volte. Senza entrare troppo nel dettaglio che eccede lo scopo di questo tutorial, setInterval
eseguirà (in questo caso) ogni cinquanta millisecondi, indipendentemente dalla durata del codice all'interno della funzione.
setInterval
è come un autista nel traffico dell'ora di punta che si rifiuta di intervenire sulle pause.
Quindi, quando possibile, combinando setTimeout
con una funzione ricorsiva è la soluzione più intelligente. Nota che assegniamo setTimeout
a una variabile, playProgressInterval
, perché in seguito è necessario cancellare questo timeout. Pertanto, abbiamo bisogno di una sorta di id da collegare.
Ora che abbiamo specificato che, ogni cinquanta millisecondi, il updatePlayProgress
il metodo dovrebbe essere chiamato, creiamo ora.
updatePlayProgress: function () playProgressBar.style.width = ((video.currentTime / video.duration) * (progressHolder.offsetWidth)) + "px";
Anche se all'inizio il codice potrebbe sembrare super confusionario, non è male. Afferriamo la barra di avanzamento e aggiorniamo la sua larghezza (ogni 50ms). Possiamo determinare la larghezza corretta dividendo la posizione corrente del video, in base alla lunghezza del video, con la quale possiamo calcolare video.duration
. Questo valore dovrebbe quindi essere moltiplicato per la larghezza totale del nostro portatore di progresso e voilà!
Ma cosa succede quando il video viene messo in pausa dall'utente? Sicuramente non vogliamo continuare questo setTimeout
. Ovviamente no. Come tale, dovremmo creare un altro metodo, chiamato stopPlayProgress
, e fare riferimento ad esso quando viene attivato l'evento di pausa.
// Abbiamo già aggiunto questo evento. Lo stiamo aggiornando solo con una nuova chiamata in basso. video.addEventListener ('pause', function () play.title = 'Riproduci'; play.innerHTML = '& # x25BA;'; // Il video è stato messo in pausa, interrompe il monitoraggio dell'avanzamento. videoPlayer.stopTrackingPlayProgress ();, falso );
// Il video è stato interrotto, quindi interrompere l'aggiornamento. stopTrackingPlayProgress: function () clearTimeout (playProgressInterval);
L'ultimo passaggio che tratteremo in questo tutorial spiega come "strofinare" il video, ovvero quando l'utente fa clic sulla barra di avanzamento e scorre su e giù per il video. Sono sicuro che tu abbia eseguito questo compito tu stesso in più occasioni. No, no, no; queste cose sono fatte automaticamente. Dobbiamo codificare quella funzionalità.
Veloce ... trattieni il respiro.
videoScrubbing: function () progressHolder.addEventListener ("mousedown", function () videoPlayer.stopTrackingPlayProgress (); videoPlayer.playPause (); document.onmousemove = function (e) videoPlayer.setPlayProgress (e.pageX); progressHolder .onmouseup = function (e) document.onmouseup = null; document.onmousemove = null; video.play (); videoPlayer.setPlayProgress (e.pageX); videoPlayer.trackPlayProgress ();, true); , setPlayProgress: function (clickX) var newPercent = Math.max (0, Math.min (1, (clickX - this.findPosX (progressHolder)) / progressHolder.offsetWidth)); video.currentTime = newPercent * video.duration; playProgressBar.style.width = newPercent * (progressHolder.offsetWidth) + "px"; , findPosX: function (progressHolder) var curleft = progressHolder.offsetLeft; while (progressHolder = progressHolder.offsetParent) curleft + = progressHolder.offsetLeft; return curleft;
... e respiro. Prendiamo questo enorme gruppo di codice riga per riga.
videoPlayer.stopTrackingPlayProgress
per cancellare il timeout che abbiamo creato sopra. play pausa
metodo che gestirà, in questo caso, mettere in pausa il video. setPlayProgress
metodo. Non ci sono due mo