Construir un reproductor de video HTML5 personalizado
Spanish (Español) translation by Elías Nicolás (you can also view the original English article)
Aunque
la idea de un elemento HTML específico de video se sugirió hace más de
una década, estamos apenas empezando a ver esto llegar a buen puerto. Olvídese de todo eso "HTML5 2012" mumbo-jumbo; La verdad es que usted puede utilizar el elemento de video en sus proyectos ahora mismo! Sólo tiene que ser consciente de un puñado de requisitos antes de despreocupadamente tomar la zambullida.
Lo que debemos saber
- Por una buena razón, la especificación no recomienda ofrecer soporte de pantalla completa. Como se puede imaginar, ahora que el video puede ser controlado con JavaScript, ¡seguramente todos podemos imaginar todas las diversas maneras en que esto puede ser abusado! Con eso dicho, las betas de algunos navegadores ofrecen el vídeo de la pantalla completa, vía un click derecho.
- Lamentablemente, si el soporte de pantalla completa es un requisito para sus necesidades que en este momento, no puede confiar en él. En su lugar, tendría que utilizar o crear un reproductor personalizado que ofrezca esta función.
- Con el fin
de obligar a Internet Explorer a reconocer los distintos elementos HTML5
nuevos, tenemos que usar un simple bit de engaño, con lo que creamos el
elemento con JavaScript, con
document.createElement ('video'). Curiosamente, esto parece activar la conciencia de IE. Sí -- es bastante extraño, pero hemos llegado a esperar eso de Internet Explorer, ¿verdad? Para acelerar este proceso, Remy Sharp creó HTML5 Shiv, que también, de paso, soluciona algunos problemas de impresión al trabajar con elementos HTML5. Basta con descargar el script y hacer referencia a él dentro de la secciónheadde sus documento(s). - Los navegadores no se llevan bastante bien cuando se trata del tipo de video que soportan. Por
ejemplo, Firefox prefiere el vídeo codificado en el formato
ogg, mientras que los navegadores Webkit pueden reproducir los videosmp4. De hecho, esto es una simplificación excesiva; Sin embargo, esto se hará por el momento. Sin embargo, basta con decir que se admiten más tipos de video, incluido el codec V8 de código abierto de Google recientemente. - Podemos ofrecer fácilmente un reproductor Flash como soporte fallback para navegadores antiguos; Así que no temas. Sin embargo, tenga en cuenta que, al menos en este momento, tendrá que convertir su vídeo en al menos dos formatos.
¿Por qué crear un reproductor personalizado?
- Soporte de pantalla completa: Por experiencia personal, puedo decirle que el problema de soporte de pantalla completa es un disyuntor. Por ejemplo, como el editor de Tuts+, no puedo ofrecer screencasts de programacion que deben ser vistos en 600px! Por esta sola razón, la construcción de un jugador personalizado es esencial.
- Marca: Cada navegador implementa su propio reproductor de video, que es ligeramente diferente de sus contrapartes. Como resultado de la construcción de un reproductor personalizado, podemos garantizar que las imágenes son consistentes de navegador a navegador ... y también llegar a la marca / piel del reproductor a nuestro corazón del contenido. Como prueba de concepto, el jugador de este tutorial usará el logo Tuts+.
Reproductor de video de Webkit



Reproductor de video de Mozilla



Nuestro reproductor de video personalizado de marca Tuts+ (en todos los navegadores)



Paso 1: El elemento vídeo
Como con cualquier proyecto, nuestro primer paso es crear el margen de beneficio necesario para nuestro proyecto.
1 |
|
2 |
<!DOCTYPE html>
|
3 |
|
4 |
<html lang="en"> |
5 |
<head>
|
6 |
<meta charset="utf-8"> |
7 |
<title>Custom HTML5 Video Player</title> |
8 |
</head>
|
9 |
<body>
|
10 |
|
11 |
<div id="container"> |
12 |
|
13 |
<h1> HTML5 Video </h1> |
14 |
|
15 |
<div id="video_container"> |
16 |
<video>
|
17 |
<source src="http://nettuts.s3.amazonaws.com/763_sammyJSIntro/trailer_test.mp4" type="video/mp4"> |
18 |
<source src="http://nettuts.s3.amazonaws.com/763_sammyJSIntro/trailer_test.ogg" type="video/ogg"> |
19 |
|
20 |
<!-- LINK TO FLASH FALLBACK PLAYER HERE. COULD BE EMBED OR OBJECT ELEMENT -->
|
21 |
</video>
|
22 |
</div>
|
23 |
|
24 |
</div>
|
25 |
|
26 |
</body>
|
27 |
</html>
|
En primer lugar, busque algunos videos de ejemplo para trabajar. El video open-source "Big Bunny Buck" como video-Pixar es el que voy a usar. Estoy seguro de que ya lo has visto en uso en la web. Ver esta marca en el navegador puede dejarle con un signo de interrogación sobre su cabeza.
El elemento video sin procesar



¿Huh? ¿Eso es todo? Simplemente se ve una imagen. ¿Cuál es el problema? Bueno, por defecto, esto es todo lo que hemos solicitado. Tenemos que entonces especificar si o no mostrar los controles, mostrar un cartel, etc. Vamos a hacer eso ahora; Revise su elemento video, así:
1 |
|
2 |
<video controls width=1000 preload poster=path/to/poster.jpg> |
Justo al revés, notamos que no hay citas alrededor de los atributos. Como resulta, no son necesarios. Mientras que hace años, se consideró una mala práctica para excluirlos, esto ya no es el caso. En este punto, sólo se reduce a la preferencia personal. Por lo tanto, si te sientes más cómodo añadirlos, entonces, por todos los medios, hazlo.
- controls: Agrega los controles estándar de reproducción / pausa al reproductor
- width: El ancho del reproductor
- preload: Indica al navegador que comience a precargar el video cuando se cargue la página. Piense dos veces antes de agregar ciegamente este atributo. Utiliza el ancho de banda del espectador cuando habilita esta función. En segundo lugar, en el momento de escribir esto, ningún navegador ha implementado esta funcionalidad todavía ... pero lo harán.
- poster: No se ha implementado completamente en todos los navegadores, esto le permite configurar una imagen como el comienzo del vídeo antes de que comience a reproducir.
El elemento Video con atributos



Paso 2: controles personalizados
Obviamente no hacemos qué usar los controles predeterminados del navegador. Como tal, debemos implementar nuestra propio marco de control. Antes
de progresar, es posible que se haya preguntado: "Entonces, ¿cuál es el
punto de agregar el atributo controls ? La
respuesta es porque debemos considerar y compensar el hecho de que
JavaScript podría estar deshabilitado en la computadora del espectador. En esos casos, si no hubiéramos añadido el atributo controls, sólo veríamos lo que parece ser una imagen.
Siempre considere la posibilidad de que JavaScript podría estar deshabilitado.
1 |
|
2 |
<div id="video_container"> |
3 |
<video controls width=1000 preload poster=assets/poster.jpg> |
4 |
<source src="http://nettuts.s3.amazonaws.com/763_sammyJSIntro/trailer_test.mp4" type="video/mp4"> |
5 |
<source src="http://nettuts.s3.amazonaws.com/763_sammyJSIntro/trailer_test.ogg" type="video/ogg"> |
6 |
<!-- FALLBACK HERE -->
|
7 |
</video>
|
8 |
|
9 |
<div id="videoControls"> |
10 |
<button id="play" title="Play"> ► </button> |
11 |
|
12 |
<div id="progress"> |
13 |
<div id="progress_box"> |
14 |
<span id="play_progress"></span> |
15 |
</div>
|
16 |
</div>
|
17 |
|
18 |
<button id="fullScreen" title="FullScreen Toggle"> FS </button> |
19 |
<a href="http://www.tutsplus.com"><img src="http://tutsplus.s3.amazonaws.com/tutspremium/web-development/103_html5VideoPlayer/images/tuts_logo.png" alt="Tuts" id="video_tutsLogo" /></a> |
20 |
</div>
|
21 |
</div>
|
La div con un id de "videoControls" es donde vamos a añadir los botones necesarios y el logotipo. Un pequeño truco ingenioso es el uso de "& #x25BA;" Para crear el botón de reproducción. No se preocupe demasiado por el "progress" div; Revisaremos esta sección con más detalle más adelante en este tutorial. La respuesta corta es que este es el contenedor de nuestra barra de progreso. Por último, añadimos un button que cambiará la funcionalidad de pantalla completa, así como el logotipo Tuts+.
Dos juegos de control a la vez?

No te preocupes; Aunque parece que ahora hemos creado un segundo conjunto de controles (y sin estilos), con el tiempo vamos a eliminar los controles predeterminados con JavaScript. Sin embargo, la captura de pantalla anterior debe coincidir con su propia vista previa, si usted está siguiendo el tutorial.
Paso 3: El JavaScript
¡Con el mark-up completo, ahora podemos pasar a la parte divertida! Cree una nueva carpeta, llamada "js", y añada un nuevo archivo: videoPlayer.js. A
continuación, vamos a ser buenos chicos y chicas y envolver nuestro
código dentro de una función anónima de auto-invocación, para evitar la
creación de variables globales innecesarias.
1 |
|
2 |
(function( window, document) {
|
3 |
|
4 |
}( this, document )) |
Usted puede quitar los argumentos si lo desea, es una pequeña mejora con dos ventajas:
- Al
pasar
this(el objeto Window global) y eldocument, evitamos que el motor JavaScript tenga que filtrar y rastrear esos objetos. Esto puede ser una gran conveniencia para proyectos más grandes, pero ofrece un beneficio de rendimiento muy pequeño. - Al minificar su JavaScript, la
windowy eldocumentahora pueden ser representados a través de algo comoayb.
A
continuación, seguiremos manteniendo nuestro código lo más limpio
posible creando un objeto videoPlayer que contenga todos nuestros
métodos. También crearemos un método init que se llamará inmediatamente cuando la página se cargue.
1 |
|
2 |
(function( window, document) {
|
3 |
var videoPlayer = {
|
4 |
init : function() {
|
5 |
|
6 |
} |
7 |
}; |
8 |
|
9 |
videoPlayer.init(); |
10 |
|
11 |
}( this, document )) |
Como seguramente estaremos manipulando elementos en la página, vamos a seguir adelante y hacer referencia a la ubicación de ellos dentro de las variables. Justo antes de declarar la variable "videoPlayer", preponer:
1 |
|
2 |
var video = document.getElementsByTagName('video')[0],
|
3 |
videoControls = document.getElementById('videoControls'),
|
4 |
play = document.getElementById('play'),
|
5 |
|
6 |
progressContainer = document.getElementById("progress"),
|
7 |
progressHolder = document.getElementById("progress_box"),
|
8 |
playProgressBar = document.getElementById("play_progress"),
|
9 |
|
10 |
fullScreenToggleButton = document.getElementById("fullScreen");
|
Si usted está trabajando a lo largo (y espero que lo son), tómese un tiempo para aprender exactamente lo que estas variables están haciendo referencia. Refiérase a su mark-up, si es necesario. Tomamos el elemento de video, los controles de video div, el botón de reproducción, el botón de alternador de pantalla completa y los tres divs de progreso. Nosotros "caché" la ubicación de estos elementos porque no hay razón para recorrer innecesariamente el DOM cada vez que necesitamos acceder a uno de estos elementos!
El método Init
Comencemos a escribir un código real. En el método init, péguelo en el siguiente fragmento:
1 |
|
2 |
init : function() {
|
3 |
// this is equal to the videoPlayer object. |
4 |
var that = this; |
5 |
|
6 |
// Helpful CSS trigger for JS. |
7 |
document.documentElement.className = 'js'; |
8 |
|
9 |
// Get rid of the default controls, because we'll use our own. |
10 |
video.removeAttribute('controls');
|
11 |
|
12 |
// When meta data is ready, show the controls |
13 |
video.addEventListener('loadeddata', this.initializeControls, false);
|
14 |
} |
Una
manera elegante de que los elementos de estilo basado en si JavaScript
está habilitado es mediante la aplicación de una clase de "js" a la
documentElement, o el elemento html.
1 |
|
2 |
// Helpful CSS trigger for JS. |
3 |
document.documentElement.className = 'js'; |
Esto nos permite escribir CSS como:
1 |
|
2 |
.js #container { |
3 |
/* this styling only renders if JS is enabled */
|
4 |
}
|
¿Recuerda el problema con los dos conjuntos de controles de vídeo? Vamos a remediar eso ahora. Esta es una fácil; Simplemente usaremos el método removeAttribute y nos deshacemos de controls.
1 |
|
2 |
// Get rid of the default controls, because we'll use our own. |
3 |
video.removeAttribute('controls');
|
Ahora añadamos nuestro primer evento HTML5: loadeddata. Este evento se activa cuando el navegador ha terminado de cargar los metadatos del vídeo. Este es un excelente lugar para realizar cualquier procedimiento inicial, como mostrar controles personalizados.
1 |
|
2 |
// When meta data is ready, show the controls |
3 |
video.addEventListener('loadeddata', this.initializeControls, false);
|
Si conoce un poco de JavaScript, puede estar preocupado de que no estamos compensando por Internet Explorer. Para aquellos que no saben, IE8 y siguientes no reconocen addEventListener. En su lugar, en la moda se ha acostumbrado a, IE utiliza su propio attachEvent. Sin embargo, todo eso está cambiando en la versión nueve del navegador. Como IE8 y para abajo no entienden el elemento vídeo, podemos ignorar completamente el evento attachEvent.
Cuando se desencadena el evento loadeddata, llamamos al método "initializeControls" que aún no se ha creado. Dentro de un método de objeto, no podemos referirnos a "initializeControls" por sí mismo. Primero debemos hacer referencia al objeto mismo: por lo tanto, this.initializeControls.
InitializeControls: Nuestros controles personalizados
Vamos a seguir adelante y crear ese método ahora.
1 |
|
2 |
initializeControls : function() {
|
3 |
// When all meta information has loaded, show controls |
4 |
videoPlayer.showHideControls(); |
5 |
} |
Como
se mencionó anteriormente, si escribe su propio reproductor
personalizado, utilice este método para realizar cualquier procedimiento
inicial adicional. Por ahora, este método llamará a otro método, showHideControls. Este nuevo método mostrará u oculta los controles cuando el usuario se sitúa sobre el vídeo.
El método showHideControls
1 |
|
2 |
showHideControls : function() {
|
3 |
// Shows and hides the video player. |
4 |
video.addEventListener('mouseover', function() {
|
5 |
videoControls.style.opacity = 1; |
6 |
}, false); |
7 |
|
8 |
videoControls.addEventListener('mouseover', function() {
|
9 |
videoControls.style.opacity = 1; |
10 |
}, false); |
11 |
|
12 |
video.addEventListener('mouseout', function() {
|
13 |
videoControls.style.opacity = 0; |
14 |
}, false); |
15 |
|
16 |
videoControls.addEventListener('mouseout', function() {
|
17 |
videoControls.style.opacity = 0; |
18 |
}, false); |
19 |
} |
Este
método asigna cuatro controladores de eventos al reproductor de vídeo y
controla los elementos, representados por las variables video y
videoControls, respectivamente. Este
código es simple: al pasar el ratón por el video, cambia la opacidad de
los controles de vídeo a 1. A la inversa, al quitar el mouse de encima,
ocultar los controles de la vista. Este
código asume también que, por defecto, dentro de nuestra hoja de
estilos, la opacity de controles de vídeo se establece en ninguno.
Recuerda: cuando sea posible, delega siempre el estilo a nuestro archivo CSS, en lugar de agregarlo directamente con tu JavaScript. Además de los beneficios de rendimiento y la reducción de los reflujos / repintados, esta práctica se adhiere correctamente a la separación de la presentación de la lógica. Sin embargo, de vez en cuando, no tendrás otra opción que agregar el estilo dentro de tu archivo JavaScript, y en esos casos, está bien.
Presionando el botón
Ahora hemos ocultado correctamente los controles predeterminados, pero todavía no hemos adjuntado ninguna lógica a estos diversos botones personalizados. Eso es lo que debemos hacer a continuación.
Vuelva al método init y agregue una llamada a un nuevo método.
1 |
|
2 |
// When play, pause buttons are pressed. |
3 |
this.handleButtonPresses(); |
Usted está, por supuesto, libre de nombrar estos métodos como desee, pero por lo menos tratar de nombrarlos de tal manera que sea fácil de entender exactamente cuál es el propósito de la función.
handleButtonPresses
1 |
|
2 |
handleButtonPresses : function() {
|
3 |
// When the video or play button is clicked, play/pause the video. |
4 |
video.addEventListener('click', this.playPause, false);
|
5 |
play.addEventListener('click', this.playPause, false);
|
6 |
|
7 |
// When the play button is pressed, |
8 |
// switch to the "Pause" symbol. |
9 |
video.addEventListener('play', function() {
|
10 |
play.title = 'Pause'; |
11 |
play.innerHTML = '<span id="pauseButton">▐▐</span>'; |
12 |
}, false); |
13 |
|
14 |
|
15 |
// When the pause button is pressed, |
16 |
// switch to the "Play" symbol. |
17 |
video.addEventListener('pause', function() {
|
18 |
play.title = 'Play'; |
19 |
play.innerHTML = '►'; |
20 |
}, false); |
21 |
|
22 |
|
23 |
// When the video has concluded, pause it. |
24 |
video.addEventListener('ended', function() {
|
25 |
this.currentTime = 0; |
26 |
this.pause(); |
27 |
}, false); |
28 |
} |
Dentro
de este método, de nuevo adjuntamos un puñado de nuevos eventos que
están disponibles para el elemento vídeo: play, pause y ended.
- play: Se dispara cuando el video empieza a reproducirse.
- pause: Se activa cuando el vídeo se detiene.
- ended: Se dispara cuando el video ha concluido. Este detector de eventos se puede utilizar para restablecer el video de nuevo al principio.
Tenga en cuenta que, por ejemplo, el evento
playno se dispara cuando hace clic en el botón de reproducción que creamos. No, en su lugar, se activa cuando el propio vídeo empieza a reproducirse. Esa es una distinción importante para recordar.
Para activar los eventos enumerados anteriormente, agregamos otro oyente de eventos al botón de reproducción y escuchamos cuando el usuario hace clic en él.
1 |
|
2 |
// When the video or play button is clicked, play/pause the video. |
3 |
play.addEventListener('click', this.playPause, false);
|
El método playPause
1 |
|
2 |
playPause: function() {
|
3 |
if ( video.paused || video.ended ) {
|
4 |
if ( video.ended ) { video.currentTime = 0; }
|
5 |
video.play(); |
6 |
} |
7 |
else { video.pause(); }
|
8 |
} |
Hablemos a través del código anterior en modo general. Cuando
se llamó a este método - en nuestro caso, cuando se hace clic en el
botón de reproducción - ¿se detuvo o al final del video? Si es este último, tenemos que restablecer la hora del video de nuevo a 0, para que pueda reproducir desde el principio de nuevo. A continuación, tenemos que reproducir el video: video.play().
Ahora,
si el video no estaba pausado o al final -- lo que significa que el
video estaba en proceso de reproducción cuando se pulsó el botón de
reproducción, debemos hacer lo contrario, y hacer una pausa en el video:
video.pause().
Cambiar los botones de reproducción / pausa
El método playPause, detallado anteriormente, maneja el proceso de reproducción o pausa del vídeo. Pero, ciertamente necesitamos proporcionar al usuario alguna información sobre lo que hace el botón, ¿verdad? Seguro; Para ello, cambiaremos un código de carácter HTML "play" y "pause" cada vez que se haga clic en el botón. Así, esencialmente, este botón maneja tanto la reproducción como la pausa.
Si nos referimos a los oyentes de eventos desde hace un momento, ya hemos añadido esta funcionalidad.
1 |
|
2 |
// When the play button is pressed, |
3 |
// switch to the "Pause" symbol. |
4 |
video.addEventListener('play', function() {
|
5 |
play.title = 'Pause'; |
6 |
play.innerHTML = '<span id="pauseButton">▐▐</span>'; |
7 |
}, false); |
8 |
|
9 |
|
10 |
// When the pause button is pressed, |
11 |
// switch to the "Play" symbol. |
12 |
video.addEventListener('pause', function() {
|
13 |
play.title = 'Play'; |
14 |
play.innerHTML = '►'; |
15 |
}, false); |
Bastante simple, ¿verdad? Si se pulsa el botón de reproducción, se activa el evento de click del botón de reproducción, que llama a video.play(). Este método reproduce el video y activa el evento de play. El evento play cambia el valor del botón a un símbolo de pausa y actualiza el atributo de título. Finalmente, cuando este proceso se repite, hacemos lo contrario.
Soporte de pantalla completa
Lo mencioné en el párrafo de apertura de este tutorial: soporte de pantalla completa es una necesidad para mí. Vamos a agregar esa funcionalidad ahora. Vuelva al método init() y, de nuevo, agregue un fragmento al fondo. Necesitamos escuchar cuando ese botón de alternador de pantalla completa que creamos...
1 |
|
2 |
<button id="fullScreen" title="FullScreen Toggle"> FS </button> |
... hace clic. Cuando lo es, deberíamos cambiar el video a pantalla completa, o lo contrario.
No olvide:
fullScreenToggleButtonse refiere al botón "fullScreen".
1 |
|
2 |
// When the full screen button is pressed... |
3 |
fullScreenToggleButton.addEventListener("click", function(){
|
4 |
isVideoFullScreen ? that.fullScreenOff() : that.fullScreenOn(); |
5 |
}, true); |
Espera un minuto: ¿qué es that? ¿No debería ser this? La respuesta es no. En el contexto del evento click, this ahora se refiere al botón "fullScreen", no al objeto videoPlayer.
Para remediar esto, "almacenaremos en caché" el valor original de this dentro de una variable, llamada that. Esto se puede agregar a la parte superior de nuestro método init().
1 |
|
2 |
init : function() {
|
3 |
// this is equal to the videoPlayer object. |
4 |
var that = this; |
5 |
... |
¡Ta da! Ahora, podemos referirnos de nuevo al objeto videoPlayer. Como tal, that.fullScreenOff significa "acceder al método llamado" fullScreenOff "que es un hijo del objeto videoPlayer.
Hay un problema. ¿Cómo determinamos el estado actual del video? ¿Es de tamaño normal o regular? Una manera fácil de manejar esta situación es crear una variable, llamada "isVideoFullScreen". Puede agregar esta variable a la parte superior de su página, junto con los demás. Por defecto, por supuesto, este valor debe establecerse en false.
1 |
|
2 |
fullScreenToggleButton = document.getElementById("fullScreen"),
|
3 |
// Boolean that allows us to "remember" the current size of the video player. |
4 |
isVideoFullScreen = false, |
Este booleano ahora nos permite llamar correctamente a la función apropiada cuando se hace clic en el botón "fullScreen".
1 |
|
2 |
isVideoFullScreen ? that.fullScreenOff() : that.fullScreenOn(); |
Usando el operador ternario, comprobamos: "¿el video está actualmente en modo de pantalla completa? Si lo es, llamamos fullScreenOff(). De lo contrario, llamamos a fullScreenOn().
1 |
|
2 |
fullScreenOn : function() {
|
3 |
isVideoFullScreen = true; |
4 |
|
5 |
// Set new width according to window width |
6 |
video.style.cssText = 'position: fixed; width:' + window.innerWidth + 'px; height: ' + window.innerHeight + 'px;'; |
7 |
|
8 |
// Apply a classname to the video and controls, if the designer needs it... |
9 |
video.className = 'fullsizeVideo'; |
10 |
videoControls.className = 'fs-control'; |
11 |
fullScreenToggleButton.className = "fs-active control"; |
12 |
|
13 |
// Listen for escape key. If pressed, close fullscreen. |
14 |
document.addEventListener('keydown', this.checkKeyCode, false);
|
15 |
}, |
16 |
|
17 |
|
18 |
fullScreenOff : function() {
|
19 |
isVideoFullScreen = false; |
20 |
|
21 |
video.style.position = 'static'; |
22 |
|
23 |
video.className = ''; |
24 |
fullScreenToggleButton.className = "control"; |
25 |
videoControls.className = ''; |
26 |
} |
Dentro de estas dos funciones, primero cambiamos el valor de isVideoFullScreen, en consecuencia. A continuación, ajustamos el tamaño del vídeo, por sí mismo. cssText nos permite pasar una cadena de estilo a un elemento. En este caso, no podemos realizar esta tarea directamente desde nuestra hoja de estilos. Esto se debe a que los valores deseados son dinámicos y dependerá del tamaño de la ventana del navegador del visitante.
Utilice
window.innerWidthywindow.innerHeight para recuperar el ancho y la altura de la ventana del navegador.
También es una buena práctica aplicar nombres de clase específicos de pantalla completa a nuestros elementos. De esa manera, si necesita agregar cualquier estilo adecuado, ahora tiene un nombre de clase para enganche.
La tecka Escape
Además del botón para alternar de pantalla completa, también es bastante común dejar el modo de pantalla completa cuando el usuario presiona la tecla de escape en su teclado. Es una buena comodidad, y es una que debemos implementar en nuestro reproductor. ¡Por suerte, es fácil!
1 |
|
2 |
// Listen for escape key. If pressed, close fullscreen. |
3 |
document.addEventListener('keydown', this.checkKeyCode, false);
|
Para escuchar clics de teclas, usamos el evento keydown. Mientras
que podría pasar una función anónima como el segundo parámetro, este
pedacito del código podría ser utilizado en varios lugares. Y cuando esto es cierto, el código debe ser reubicado a su propia función, para su reutilización. Lo llamaremos, checkKeyCode.
checkKeyCode
1 |
|
2 |
// Determines if the escape key was pressed. |
3 |
checkKeyCode : function( e ) {
|
4 |
e = e || window.event; |
5 |
if ( (e.keyCode || e.which) === 27 ) videoPlayer.fullScreenOff(); |
6 |
} |
Esta función es, por desgracia, más confusa de lo que debería ser, debido a los problemas de Internet Explorer. No estoy seguro de cómo el próximo IE9 maneja el objeto de evento, por lo que, por el momento, vamos a compensar las discrepancias entre la forma en que IE y los otros navegadores modernos manejan el objeto de evento.
Cosas aburridas aparte, este código comprueba si la clave que se ha hecho clic tiene un código de "27." Si
lo hace, entonces se pulsa la tecla "Escape", en cuyo caso podemos
salir de la pantalla completa, a través de videoPlayer.fullScreenOff().
Seguimiento del Progreso
Por último, pero no menos importante, necesitamos seguir el progreso del video. Por lo tanto, a medida que avanza el video, necesitamos proporcionar un "depurador" de progreso que ayudará a rastrear el video. Además, permite al usuario escanear rápidamente a su parte deseada del video.
¿Cuándo debemos comenzar a rastrear?
Eso es fácil: ¡cuando el video está reproduciendo! Así
que, con eso en mente, modifiquemos nuestro código de evento play y llamemos a una función que rastreará el progreso del
video.
1 |
|
2 |
// When the play button is pressed, |
3 |
// switch to the "Pause" symbol. |
4 |
video.addEventListener('play', function() {
|
5 |
play.title = 'Pause'; |
6 |
play.innerHTML = '<span id="pauseButton">▐▐</span>'; |
7 |
|
8 |
// Begin tracking video's progress. |
9 |
videoPlayer.trackPlayProgress(); |
10 |
}, false); |
trackPlayProgress
1 |
|
2 |
// Every 50 milliseconds, update the play progress. |
3 |
trackPlayProgress : function(){
|
4 |
(function progressTrack() {
|
5 |
videoPlayer.updatePlayProgress(); |
6 |
playProgressInterval = setTimeout(progressTrack, 50); |
7 |
})(); |
8 |
} |
No dejes que este código te asuste. Es
simplemente una función recursiva que nos permite llamar a un método
diferente, updatePlayProgress(), cada cincuenta milisegundos. ¿Por qué no usar setInterval? Esto es porque setInterval puede ser desagradable a veces. Sin
entrar en demasiados detalles que exceda el alcance de este tutorial,
setInterval se ejecutará (en este caso) cada cincuenta milisegundos,
independientemente del tiempo que dure el código dentro de la función.
SetIntervales como un conductor en el tráfico de hora punta que se niega a pisar los frenos.
Por lo tanto, cuando es posible, la combinación de setTimeout con una función recursiva es la solución más inteligente. Tenga
en cuenta que asignamos setTimeout a una variable,
playProgressInterval, porque necesitamos borrar más tarde este tiempo de
espera. Por lo tanto, necesitamos algún tipo de identificación al cual conectarse.
updatePlayProgress
Ahora
que hemos especificado que, cada cincuenta milisegundos, el método
updatePlayProgress debe ser llamado, vamos a crearlo ahora.
1 |
|
2 |
updatePlayProgress : function(){
|
3 |
playProgressBar.style.width = ( (video.currentTime / video.duration) * (progressHolder.offsetWidth) ) + "px"; |
4 |
} |
Aunque el código de arriba puede parecer ser muy confuso al principio, no es demasiado malo. Tomamos la barra de progreso y actualizamos su ancho (cada 50ms). Podemos
determinar el ancho correcto dividiendo la ubicación actual del video,
por la longitud del video - que podemos calcular con video.duration. Este valor debe ser multiplicado por el ancho total de nuestro lugar de progreso, ¡y voila!
Pero, ¿qué sucede si el video se detiene por el usuario? Seguramente no queremos continuar con este setTimeout. Por supuesto que no. Como tal, debemos crear otro método, llamado stopPlayProgress, y referirnos a él cuando se dispara el evento de pausa.
1 |
|
2 |
// We've already added this event. We're only updating it with one new call at the bottom. |
3 |
video.addEventListener('pause', function() {
|
4 |
play.title = 'Play'; |
5 |
play.innerHTML = '►'; |
6 |
|
7 |
// Video was paused, stop tracking progress. |
8 |
videoPlayer.stopTrackingPlayProgress(); |
9 |
}, false); |
1 |
|
2 |
// Video was stopped, so stop updating progress. |
3 |
stopTrackingPlayProgress : function(){
|
4 |
clearTimeout( playProgressInterval ); |
5 |
} |
Depuracion de Video
El paso final que cubriremos en este tutorial explica cómo "limpiar" el video, es decir, cuando el usuario hace clic en la barra de progreso y se desplaza hacia arriba y hacia abajo del vídeo. Estoy seguro de que ha realizado esta tarea usted mismo en múltiples ocasiones. No no no; Estas cosas no se hacen automáticamente. Tenemos que programar esa funcionalidad.
Rápido ... contenga la respiración.
1 |
|
2 |
videoScrubbing : function() {
|
3 |
progressHolder.addEventListener("mousedown", function(){
|
4 |
videoPlayer.stopTrackingPlayProgress(); |
5 |
|
6 |
videoPlayer.playPause(); |
7 |
|
8 |
document.onmousemove = function(e) {
|
9 |
videoPlayer.setPlayProgress( e.pageX ); |
10 |
} |
11 |
|
12 |
progressHolder.onmouseup = function(e) {
|
13 |
document.onmouseup = null; |
14 |
document.onmousemove = null; |
15 |
|
16 |
video.play(); |
17 |
videoPlayer.setPlayProgress( e.pageX ); |
18 |
videoPlayer.trackPlayProgress(); |
19 |
} |
20 |
}, true); |
21 |
}, |
22 |
|
23 |
setPlayProgress : function( clickX ) {
|
24 |
var newPercent = Math.max( 0, Math.min(1, (clickX - this.findPosX(progressHolder)) / progressHolder.offsetWidth) ); |
25 |
video.currentTime = newPercent * video.duration; |
26 |
playProgressBar.style.width = newPercent * (progressHolder.offsetWidth) + "px"; |
27 |
}, |
28 |
|
29 |
findPosX : function(progressHolder) {
|
30 |
var curleft = progressHolder.offsetLeft; |
31 |
while( progressHolder = progressHolder.offsetParent ) {
|
32 |
curleft += progressHolder.offsetLeft; |
33 |
} |
34 |
return curleft; |
35 |
} |
... y la exhale. Tomemos este gran grupo de código línea por línea.
- Escuchar cuando el usuario hace clic en la barra de progreso.
- Cuando lo hacen, llamar a
videoPlayer.stopTrackingPlayProgresspara borrar el tiempo de espera que creamos anteriormente. - A continuación, llame al método
playPauseque manejará, en este caso, pausar el video. - Mientras el ratón sigue siendo presionado, escuche cuando se mueve. Cuando lo hace, llame al método
setPlayProgress. - Este método complicado es difícil de explicar con palabras; Tendrás que estudiarlo un poco. Esencialmente, el código determina dónde hizo clic y, a continuación, divide todo el ancho de la barra de progreso. A continuación, actualiza la hora actual del vídeo y el ancho de la barra dinámica de progreso.
- Después de que esta función regrese, escuchamos cuando el usuario desplaza el ratón para arriba de su click original.. Cuando lo hacen, borramos cualquier evento de ratón existente, y procedemos con la reproducción del video, así como el seguimiento de su progreso de nuevo.
Conclusion
No hay dos maneras de hacerlo; Esta materia es confusa, hasta que usted oiga repentinamente el "click," por así decirlo. Esto generalmente es procedido por un extendido, "Oooohhhhhh." Si aún no has llegado allí, si tus ojos no pudieron evitar esmaltar sobre este largo tutorial, está bien. Lea de nuevo y, lo más importante, siga avanzado a la par. Esa es la única forma de crecer. En segundo lugar, grandes trozos de código de nuestro reconocidamente difícil de tomar en todos a la vez. Para compensar, lea a través de este tutorial de nuevo en pedacitos, como tambien ve el código de fuente final. Esto ayudará a su mente a comprender exactamente a donde cada bloque de código pertenece.
En
el aspecto visual, lo maravilloso de un reproductor personalizado como este
es que, una vez que la lógica se ha escrito, es 100% compatible con pieles. Simplemente rastree sus ids y class deseados, y ya está todo listo. La demo proporcionada con este tutorial ofrece una opción, sin embargo, si no te gusta el aspecto si, no hay problema; ¡Diseñe los propios!



¿Que sigue?
Tenemos un jugador limpio y funcional en este momento, sin embargo, se puede ampliar más. En la próxima lección (gratis para usted), aprenderemos a agregar un control de volumen, así como un temporizador a nuestros controles de video. Así que esté atento.



