Un poco de diversión inocente con video HTML y progreso.
La idea surgió mientras veía un vídeo de formación obligatoria sobre el acoso laboral. Puedo escuchar a Geoff de decir secundaria LOL acerca de que un débil como yo tiene que mirar esa cosa.
Pero aquí estamos.
La interfaz de usuario del vídeo era realmente encantadora, pero fue la barra de progreso lo que realmente llamó mi atención, o más bien el archivo [progress].value
. Era un degradado simple que iba del verde al azul y crecía a medida que el vídeo continuaba reproduciéndose.
Ya sé que es posible crear el mismo gradiente de clasificación en el progress
elemento. Pankaj Parashar lo demostró en una publicación de CSS-Tricks en 2016.
Realmente quería hacer una maqueta de algo similar, pero no jugó mucho con el video. Tampoco soy un experto en JavaScript. ¿Pero qué tan difícil puede ser eso en realidad? Quiero decir, todo lo que quiero hacer es saber qué tan lejos estamos en el video y usarlo para actualizar el valor de progreso. ¿Bien?
Mi matón interior se burló tanto de mí que decidí intentarlo. No es lo más complicado del mundo, pero me divertí un poco y quería compartir cómo lo configuraré en esta demostración.
el marcado
¡HTML5 hasta el final, cariño!
figure video src="https://html5videoformatconverter.com/data/images/happyfit2.mp4"/video figcaption button aria-label="Play" role="button"►/button progress max="100" value="0"Progress/progress /figcaption/figure
La línea clave es esta:
progress max="100" value="0"Progress/progress
El max
atributo nos dice que estamos trabajando con 100 como el valor más alto mientras que el value
atributo comienza en cero. Eso tiene sentido ya que nos permite pensar en el progreso del vídeo en términos de un porcentaje, donde 0% es el inicio y 100% es el final, y donde nuestro punto de partida inicial es 0%.
estilo
Definitivamente no voy a profundizar en el proceso de diseño del progress
elemento en CSS. La publicación de Pankaj que vinculé anteriormente ya hace un trabajo fenomenal al respecto. El CSS que necesitamos para pintar un degradado en el valor de progreso se ve así:
/* Fallback stuff */progress[value] { appearance: none; /* Needed for Safari */ border: none; /* Needed for Firefox */ color: #e52e71; /* Fallback to a solid color */}/* WebKit styles */progress[value]::-webkit-progress-value { background-image: linear-gradient( to right, #ff8a00, #e52e71 ); transition: width 1s linear;}/* Firefox styles */progress[value]::-moz-progress-bar { background-image: -moz-linear-gradient( right, #ff8a00, #e52e71 );}
El truco consiste en prestar atención a los diversos matices que lo hacen compatible con todos los navegadores. Tanto los navegadores WebKit como Mozilla tienen sus propias formas particulares de manejar los elementos de progreso. Eso hace que el estilo sea un poco detallado pero, oye, ¿qué puedes hacer?
Obtener el valor de progreso de un video
Sabía que habría que hacer algunos cálculos si quería obtener el tiempo actual del vídeo y mostrarlo como un valor expresado como porcentaje. Y si pensabas que ser un nerd en la escuela secundaria me dio superpoderes matemáticos, bueno, lamento decepcionarte.
Tuve que escribir un resumen de lo que pensé que debía suceder:
- Obtenga la hora actual del vídeo. Tenemos que saber dónde está el video si queremos mostrarlo como valor de progreso.
- Obtenga la duración del vídeo . Conocer la duración del video ayudará a expresar el tiempo actual como un porcentaje.
- Calcule el valor del progreso. Nuevamente, estamos trabajando en porcentajes. Mi polvoriento libro de texto de álgebra me dice que la fórmula es
part / whole = % / 100
. En el contexto del vídeo, podemos reescribirlo comocurrentTime / duration = progress value
.
Eso nos da todas las órdenes de marcha que necesitamos para empezar. De hecho, podemos comenzar a crear variables para los elementos que necesitamos seleccionar y determinar con qué propiedades debemos trabajar para completar la ecuación.
// Variablesconst progress = document.getElementById( "progress" );// Properties// progress.value = The calculated progress value as a percent of 100// video.currentTime = The current time of the video in seconds// video.duration = The length of the video in seconds
No está mal, no está mal. Ahora necesitamos calcular el valor del progreso ingresando esas cosas en nuestra ecuación.
function progressLoop() { setInterval(function () { document.getElementById("progress").value = Math.round( (video.currentTime / video.duration) * 100 ); });}
Lo admito: olvidé que la ecuación daría como resultado valores decimales. Ahí es donde Math.round()
entra en juego actualizarlos al número entero más cercano.
¡Eso realmente hace que la barra de progreso del degradado se anime mientras se reproduce el video!
Pensé que considerar podría esto una victoria y marcharme feliz. Pero había un par de cosas que me molestaban. Además, recibía errores en la consola. No bueno.
Mostrando la hora actual
No es gran cosa, pero ciertamente es bueno tenerlo. Podemos colocar un temporizador al lado de la barra de progreso y contar segundos a medida que avanzamos. Ya tenemos los datos para hacerlo, así que todo lo que necesitamos es el marcado y conectarlo.
Agreguemos un ajuste del tiempo en label
ya que el progress
elemento puede tener uno.
figure video controls src="https://html5videoformatconverter.com/data/images/happyfit2.mp4"/video figcaption label for="progress" role="timer"/label progress max="100" value="0"Progress/progress /figcaption/figure
Ahora podemos conectarlo. Le asignaremos una variable y la usaremos innerHTML
para imprimir el valor actual dentro de la etiqueta.
const progress = document.getElementById("progress");const timer = document.getElementById( "timer" );function progressLoop() { setInterval(function () { progress.value = Math.round((video.currentTime / video.duration) * 100); timer.innerHTML = Math.round(video.currentTime) + " seconds"; });}progressLoop();
¡Oye, eso funciona!
El crédito adicional implicaría convertir el temporizador para que se muestree en HH:MM:SS
formato.
Agregar un botón de reproducción
El hecho de que hubiera dos UI funcionando al mismo tiempo me molestó. el video
elemento tiene un controls
atributo que, cuando se usa, muestra los controles del video, como reproducción, progreso, salto, volumen, etc.
Pero eso significa que necesitamos, como mínimo, proporcionar una forma de iniciar y detener el vídeo. Abotonemos eso.
Primero, agregue el HTML:
figure video src="https://html5videoformatconverter.com/data/images/happyfit2.mp4"/video figcaption label for="progress" role="timer"/label button aria-label="Play" role="button"►/button progress max="100" value="0"Progress/progress /figcaption/figure
Luego, conéctelo con una función que alterna el video entre reproducir y pausar al hacer clic.
button = document.getElementById( "play" );function playPause() { if ( video.paused ) { video.play(); button.innerHTML = "❙❙"; } else { video.pause(); button.innerHTML = "►"; }}button.addEventListener( "click", playPause );video.addEventListener("play", progressLoop);
¡Oye, todavía está funcionando!
Sé que parece extraño eliminar el amplio conjunto de controles que ofrece HTML5 de forma inmediata. Probablemente no haría eso en un proyecto real, pero aquí solo estamos jugando.
Limpiando mi feo código de espagueti
Realmente quiero agradecer a mi amigo Neal Fennimore. Se tomó el tiempo para analizar esto conmigo y ofrecerme consejos que no solo hacen que el código sea más legible, sino que también definen los estados mucho mejor…
// Statesconst PAUSED = 'paused';const PLAYING = 'playing';// Initial statelet state = PAUSED;
…haciendo una verificación adecuada del estado antes de activar la función de progreso mientras escucha los eventos de reproducción, pausa y clic…
// Animation loopfunction progressLoop() { if(state === PLAYING) { progress.value = Math.round( ( video.currentTime / video.duration ) * 100 ); timer.innerHTML = Math.round( video.currentTime ) + ' seconds'; requestAnimationFrame(progressLoop); }}video.addEventListener('play', onPlay);video.addEventListener('pause', onPause);button.addEventListener('click', onClick);
…e incluso hacer que la animación tenga más rendimiento reemplazándola setInterval
con requestAnimationFrame
como puedes ver resaltado en ese mismo fragmento.
¡Aquí está en todo su esplendor!
Ah, y sí: estaba trabajando en esto mientras “veía” el video de capacitación. Y al final superé el cuestionario, muchas gracias.
Deja un comentario