Sesion 7 HTML Parte 2 - jesusgpa/2023-2024-CSAAI GitHub Wiki

Sesión 7: HTML (Parte 2)

  • Tiempo: 2h (50 + 50min)
  • Fecha: Jueves 19 de Marzo de 2024
  • Objetivos de la sesión:
    • Aprender nuevos elementos de HTML y su control con Javascript: Control de la interfaz, lectura de teclas, Sonidos y reproducción de vídeo

Contenido

Introducción

En esta sesión veremos más elementos de HTML y ejemplos de cómo usarlos desde Javascript: elementos para interfaces de control (checkboxes, sliders, teclas...), lectura del teclado y reproducción de Audio y vídeo

Elementos de interfaz con el usuario

En HTML existen elementos de interfaz para que el usuario introduzca datos y los reciban nuestras aplicaciones Javascript.

Ya conocemos uno de ellos: los botones.

Con ellos el usuario introduce los números y operaciones en la calculadora.

Pero existen otros elementos: entradas de texto, de color, de fichero, de números, deslizadores, selectores...

Sólo veremos ejemplos de algunos de ellos.

Se utilizan con las etiquetas <input> y <select>.

Puedes encontrar más información en esta pagina de documentación de Mozilla

Con la etiqueta <input> se utiliza el atributo type cuyo valor determina el tipo de elemento de entrada a utilizar

Botones

Estos son algunos de los botones que podemos usar en nuestras interfaces

Botones normales

Estos botones son botones de acción genéricos y se utilizan comúnmente para ejecutar JavaScript cuando se hace clic en ellos.

No tienen un comportamiento predeterminado definido en HTML, por lo que se pueden utilizar para ejecutar cualquier tipo de función o acción deseada.

La cadena asignada al atributo value es la que se muestra al renderizar el botón.

  • Atributo type: button
  • Evento: click
  • Documentación: MDN Web: Button
  • Ejemplo:
<input type="button" value="Botón">

Botones de imagen

Los botones de tipo imagen en HTML se crean utilizando la etiqueta <input> con el atributo type establecido en "image".

Estos botones permiten a los usuarios hacer clic en una imagen en lugar de un botón de texto tradicional.

Este es un ejemplo de cómo se crea un botón de tipo imagen:

  • Atributo type: image
  • Evento: click
  • Documentación: MDN Web: Button
  • Ejemplo:
<input type="image" src="ruta_a_la_imagen.jpg" alt="Descripción de la imagen">

En este ejemplo:

  • type="image": Define que este elemento <input> es un botón de tipo imagen.
  • src="ruta_a_la_imagen.jpg": Especifica la ruta de la imagen que se utilizará como el botón. Esta imagen será visible en lugar de un botón de texto.
  • alt="Descripción de la imagen": Proporciona un texto alternativo que describe la imagen, mejora la accesibilidad y para los casos en que la imagen no se pueda cargar.

Cuando el usuario hace clic en este botón de tipo imagen, el formulario (si está presente) se enviará de la misma manera que lo haría con un botón de tipo "submit".

La coordenada del clic también se envía como parte del formulario, lo que puede ser útil para determinar dónde hizo clic el usuario en la imagen.

Botones de tipo "submit"

Estos botones se utilizan generalmente dentro de formularios (<form>) y se utilizan para enviar el formulario al servidor para su procesamiento.

Cuando se hace clic en un botón de tipo "submit", se envían los datos del formulario al servidor especificado en el atributo action del elemento <form>.

  • Atributo type: submit
  • Evento: click
  • Documentación: MDN Web: Button
  • Ejemplo:
<button type="submit">Enviar</button>

Botones de tipo "reset"

Estos botones se utilizan para restablecer los campos de un formulario a sus valores predeterminados.

Al hacer clic en un botón de tipo "reset", todos los campos de entrada dentro del formulario se restablecerán a sus valores originales.

Aunque no es muy recomendable utilizarlos porque puede ser muy frustrante para los usuarios si le dan por error y tienen que volver a rellenar todo el formulario. La tendencia es facilitar a los usuarios la labor de rellenar un formulario.

  • Atributo type: reset
  • Evento: click
  • Documentación: MDN Web: Button
  • Ejemplo:
<button type="reset">Restablecer</button>

Estos tipos de botones son los más comunes para la creación de botones genéricos y de acción en páginas web.

Botones de verificación ✅️

Son elementos que pueden estar en dos estados: Verificado o no.

Al pinchar con el ratón su estado cambia.

En el estado verificado el botón queda marcado con tìpico símbolo: ✅️.

No tiene cadena de texto asociada.

La tenemos que colocar nosotros como un elemento separado.

  • Atributo type: checkbox
  • Evento: change. Se genera cada vez que el botón cambia de estado
  • Documentación: MDN Web: Checkbox
  • Ejemplo: Dos botones de verificación, uno activado y otro no
<input type="checkbox">
<input type="checkbox" checked>

Botones de Radio

Son botones que sólo pueden estar en dos estados, como los de verificación, pero sólo uno de ellos puede estar activado.

Al pinchar sobre otro diferente se activa el nuevo y se desactiva el anterior, estando siempre sólo uno activo.

Para que varios botones pertenezcan al mismo grupo (y por tanto que sólo uno pueda estar activado a la vez) se les debe asignar el mismo nombre en el atributo name.

  • Atributo type: radio
  • Evento: change. Se genera cada vez que se ha activado un botón diferente
  • Documentación: MDN Web: radio
  • Ejemplo: Tres botones de radio que pertenecen al mismo grupo (grupo1).

El primero está seleccionado inicialmente.

    <input type="radio" name="grupo1" checked>
    <input type="radio" name="grupo1">
    <input type="radio" name="grupo1"> 

Ejemplo 1: Probando los tipos de botones

En este ejemplo se colocan botones de algunos de los tipos que hemos visto: normales, imagen, de verificación y radio, para compararlos.

Este es el código HTML:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <link rel="stylesheet" href="Ej-01.css">

    <script src="Ej-01.js" defer></script>
    
    <title>Ejemplo 1: Botones</title>
</head>
<body>
    <h2>Ej-1: Tipos de botones</h2>
    <hr>
    <h3>Tipo Button</h3>
    <p> <input type="button" value="Boton" id="button"> <span id="button-test">Test</span></p>

    <h3>Botón tipo imagen</h3>
    <p> <input type="image" id="btimage" src="logo-urjc.png" alt="Logo urjc"> <span id="btimage-test">Test Imagen</span></p>
    

    <h3>Tipo Checkbox</h3>
    <p> <span id="c1_test">c1</span> <input type="checkbox" id="checkbox1" > 
        <span id="c2_test">c2</span> <input type="checkbox" id="checkbox2" checked> </p>

    <h3>Tipo Radio</h3>
    <p>
        b1 <input type="radio" name="grupo1" value=1 id="radio1" checked>
        b2 <input type="radio" name="grupo1" value=2 id="radio2">
        b3 <input type="radio" name="grupo1" value=3 id="radio3">
        b4 <input type="radio" name="grupo1" value=4 id="radio4">
    </p>
    <p id="radio_display"></p>
    <hr>
        
</body>
</html>

Vamos a necesitar una pizca de css:

#btimage {
    width: 40px;
    height: 50px;
}

Este es el aspecto que tiene:

Este es el fichero Javascript:

  • Fichero: Ej-01.js
//-- Boton normal
const button = document.getElementById("button");
const button_test = document.getElementById("button-test");

//-- Botón imagen
const ibutton = document.getElementById("btimage");
const ibutton_test = document.getElementById("btimage-test")

//-- Checkbox
const c1 = document.getElementById("checkbox1");
const c2 = document.getElementById("checkbox2");
const c1_test = document.getElementById("c1_test");
const c2_test = document.getElementById("c2_test");

//-- Botones radio
const r1 = document.getElementById("radio1");
const r2 = document.getElementById("radio2");
const r3 = document.getElementById("radio3");
const r4 = document.getElementById("radio4");
const r_disp = document.getElementById("radio_display");

//-- Boton normal
button.onclick = () => {
    //-- Cambiar de color el texto
    if (button_test.style.color == "") {
        button_test.style.color = "green";
    } else {
        button_test.style.color = "";
    }
}

//-- Botón imagen
ibutton.onclick = () => {
    //-- Cambiar de color el texto
    if (ibutton_test.style.color == "") {
        ibutton_test.style.color = "red";
    } else {
        ibutton_test.style.color = "";
    }
}

//---- Botones checkbox
c1.onchange = () => {
    if (c1.checked) {
        c1_test.style.color = "red";
    } else {
        c1_test.style.color = "";
    }
}

c2.onchange = () => {
    if (c2.checked) {
        c2_test.style.color = "red";
    } else {
        c2_test.style.color = "";
    }
}

//-- Botones radio

r1.onchange = () => {
    r_disp.innerHTML = "b1";   
}

r2.onchange = () => {
    r_disp.innerHTML = "b2";   
}

r3.onchange = () => {
    r_disp.innerHTML = "b3";   
}

r4.onchange = () => {
    r_disp.innerHTML = "b4";   
}

Entradas de texto

Mediante estos elementos el usuario puede introducir cadenas de texto de diferentes maneras.

Texto normal

El usuario puede introducir cualquier cadena de caracteres.

Una vez que ha terminado debe pulsar la tecla ENTER.

El atributo placeholder permite establecer el número de caracteres máximo que se pueden introducir.

El atributo placeholder se usa para introducir un valor de ejemplo dentro de la caja del texto, o un comentario sobre algo.

El atributo size establece la anchura visible de la entrada, en caracteres.

  • Atributo type: text
  • Eventos:
    • Change. Se genera cada vez que se pulsa enter para indicar que el texto se ha finalizado
    • Input. Se emite cada vez que el usuario inserta un carácter o lo borra
  • Documentación: MDN Web: text
  • Ejemplo: Dos entradas de texto.

La segundo está limitada a 20 caracteres e incluye un comentario en su interior.

    <p> <input type="text"> </p>
    <p> <input type="text" maxlength=20 placeholder="máximo 20 caracteres"> </p>

También se pueden añadir valores opcionales, que podrá seleccionar el usuario, en vez de escribirlos.

Esto se hace con el atributo list.

Hay que asignarle el identificador de la etiqueta datalist que contiene las opciones.

<label for="myBrowser">Elige un navegador de la lista:</label>
<input list="browsers" id="myBrowser" name="myBrowser" />
<datalist id="browsers">
  <option value="Chrome"></option>
  <option value="Firefox"></option>
  <option value="Opera"></option>
  <option value="Safari"></option>
  <option value="Microsoft Edge"></option>
</datalist>

Texto oculto (passwords)

Cuando el usuario tiene que introducir una clave (password) o cierta información sensible que no queremos que se vea, utilizamos las entradas de texto de tipo password.

Cada vez que se añade un carácter en la entrada se mostrará un * o un punto (●).

  • Atributo type: password
  • Eventos:
    • Change. Se genera cada vez que se pulsa enter para indicar que el texto se ha finalizado
    • Input. Se emite cada vez que el usuario inserta un carácter o lo borra
  • Documentación: MDN Web: password
  • Ejemplo: Introduciendo una clave
    <p> <input type="password"> </p>

Ejemplo 2: Entradas de texto

Se colocan 4 entradas de texto para comprobar su funcionamiento.

La primera es una entrada normal, en la que no se usa ningún atributo adicional.

Se asocia a sus dos eventos: input y change.

Cuando se escribe o borra un carácter aparece la cadena Escribiendo... a su derecha, y al apretar ENTER se escribe su valor final.

La segunda entrada está limitada a 10 caracteres.

Se usa el evento change para escribir su valor en la derecha.

La tercera entrada es también texto normal, pero se han definido 3 opciones que el usuario puede elegir, si quiere: Opción 1, Opción 2 y Opción 3.

Con cada una de ella se introduce el texto "1", "2" ó "3".

Por último, la cuarta es una entrada de texto tipo password en la que no se ve lo que se introduce.

Al apretar ENTER se muestra el valor en la derecha, para comprobar que se ha introducido correctamente.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="Ej-02.js" defer></script>
    <title>Ejemplo 2: Entradas de texto</title>
</head>
<body>
    <h2>Ej-2: Entradas de texto</h2>
    <hr>
    <h3>Normal</h3>
    <p> Text <input type="text" id="text1"> <span id="text1_disp"></span></p>
    <p> Text <input type="text" id="text2" maxlength=10 placeholder="Max. 10 caracteres"> 
        <span id="text2_disp"></span>
    </p>
    <p>
        Text
        <input type="text" id ="text3" list="items" placeholder="Con valores predefinidos...."/>
        <span id="text3_disp"></span>
            <!-- Lista de opciones -->
            <datalist id="items">
                <option value="1">Opción 1</option>
                <option value="2">Opción 2</option>
                <option value="3">Opción 3</option>
            </datalist>
    </p>
    <h3>Oculto</h3>
    <p>password <input type="password" maxlength=10 id="passw"> <span id="passw_disp"></span>  </p>
        
</body>
</html>
  • Fichero Javascript: Ej-02.js
//-- Entradas de texto 1,2 y 3 con sus párrafos de visualización
const text1 = document.getElementById("text1");
const text1_disp = document.getElementById("text1_disp");
const text2 = document.getElementById("text2");
const text2_disp = document.getElementById("text2_disp");
const text3 = document.getElementById("text3");
const text3_disp = document.getElementById("text3_disp");

//-- Entrada de texto tipo password y su display asociado
const passw = document.getElementById("passw");
const passw_disp = document.getElementById("passw_disp");

//-- Retrollamadas de la entrada 1
text1.oninput = () => {
    text1_disp.innerHTML = "Escribiendo..."
}

text1.onchange = () => {
    text1_disp.innerHTML=text1.value;
}

//-- Retrollamada de la entrada 2
text2.onchange = () => {
    text2_disp.innerHTML = text2.value; 
}

//-- Retrollamada de la entrada 3
text3.onchange = () => {
    text3_disp.innerHTML = text3.value; 
}

//-- Retrollamada de la entrada 4
passw.onchange = () => {
    passw_disp.innerHTML = passw.value;
}

En esta animación se muestra el funcionamiento:

Entradas de números

Hay dos tipos de entradas input que nos permiten introducir números: numbery range.

En el primero el usuario escribe el número en la caja de texto.

En el segundo se usa un deslizador.

Números en caja de texto

Es una entrada de texto normal, pero que sólo genera el evento change si lo que se ha introducido es un número válido.

El usuario puede introducir cualquier carácter, pero sólo se acepta si son números.

Con los atributos min y max se establecen los valores mínimo y máximo válidos, respectivamente.

Con el atributo step se indica la precisión.

For defecto es 1, por lo que sólo se pueden introducir números enteros.

Para introducir número decimales habría que ponerlo a 0.1 ó 0.01.

En la parte derecha aparecen una fechas que nos permite incrementar o decrementar el número actual la cantidad step.

  • Atributo type: number
  • Eventos:
    • Change. Se genera cada vez que se pulsa enter y lo introducido es un número válido
    • Input. Se emite cada vez que el usuario inserta un carácter o lo borra
  • Documentación: MDN Web: number
  • Ejemplo: Introduciendo un número
    <p> <input type="number"> </p>

Deslizadores

Los deslizadores permiten introducir números de forma aproximada y muy rápida, dentro de un rango.

Se usan por ejemplo para controlar el volumen, la luminosidad, el brillo, el contraste, etc...

Visualmente son diferentes a las entradas de texto numéricas anteriores, pero el funcionamiento es similar: usa los mismos atributos min, max y step.

  • Atributo type: Range
  • Eventos:
    • Change. Se genera cada vez que hay un valor final en el deslizador (cuando se deja de arrastrar el deslizador)
    • Input. Se emite cada vez que el usuario mueve el desplizador (con el botón del ratón apretado)
  • Documentación: MDN Web: range
  • Ejemplo: Deslizador genérico
    <p> <input type="range"> </p>

Ejemplo 3: Introduciendo números

Se coloca una caja de texto numérica y un deslizador.

Cada vez que se introduce un número válido en la caja se muestra en la parte derecha.

Al mover el deslizador se muestra el valor actual en la parte derecha.

Al dejar de moverlo se visualiza también el valor final.

Para ello se capturan los dos eventos: input y change.

Código html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="Ej-03.js" defer></script>
    <title>Ejemplo 3: Entrada de números</title>
</head>
<body>
    <h2>Ej-3: Entrada de números</h2>
    <hr>
    <h3>Caja de texto</h3>
    <p> Number <input type="number" id="num1"> <span id="num1_disp"></span></p>
    <h3>Deslizador</h3>
    <p>Range <input type="range" id="range"> <span id="range_disp"></span>  
        Valor final: <span id="range_disp2"></span>
    </p>
        
</body>
</html>
  • Fichero Javascript: Ej-03.js
const num1 = document.getElementById("num1");
const num1_disp = document.getElementById("num1_disp");

const range = document.getElementById("range");
const range_disp = document.getElementById("range_disp");
const range_disp2 = document.getElementById("range_disp2");

num1.onchange = () => {
    if (num1.value != "") {
      num1_disp.innerHTML = num1.value;
    }
}

range.oninput = () => {
    range_disp.innerHTML = range.value;
}

range.onchange = () => {
  range_disp2.innerHTML = range.value;
}

En esta animación se muestra el funcionamiento:

Manejando las teclas

Todas las teclas que se aprietan en la ventana del navegador se pueden detectar desde nuestros programas en javascript a través del objeto window.

Hay dos eventos relacionados con las teclas: keydown, cuando se aprieta la tecla y keyup cuando se suelta.

Así, para que se ejecute un función de retrollamada al apretarse una tecla cambiamos el manejador window.onkeydown.

Ejemplo 4: Detectando una tecla

En este ejemplo se cambia el color del fondo de la página cada vez que se aprieta la tecla ESPACIO.

El color se modifica al cambiar la activación de la clase color.

  • Fichero Ej-04-teclas-1.html:
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="Ej-04.css">
    <script src="Ej-04.js" defer></script>
    <title>Ejemplo 4: Teclas-1</title>
</head>
<body>
    <p>Pulsa la tecla ESPACIO</p>
</body>
</html>
  • Fichero Ej-04.css:
/*
   Clase color. Cambiar el color
   del fondo
*/
.color {
    background: lightblue;
  }
  • Fichero Ej-04.js:
//-- Acceder al cuerpo del documento HTML
//-- Es el primer elemento, porque sólo hay un cuerpo
body = document.getElementsByTagName('body')[0]

//-- Función de retrollamada de tecla pulsada
window.onkeydown = (e) => {
  
  //-- Comprobar si la tecla es un espacio
  if (e.key == ' ') {

    //-- Cambiar la activación de la clase color
    body.classList.toggle("color");
  }
}

Observa cómo para acceder al cuerpo estamos usando el método getElementsByTagName().

Devuelve un array con todos los elementos del DOM cuya etiqueta es el nombre pasado como argumento.

También lo podríamos haber hecho como hasta ahora: identificando el cuerpo y llamando a getElementById().

La tecla pulsada se detecta comprobando el valor de la propiedad e.key.

Si es igual a un espacio ' ' entonces cambiamos el color.

Fíjate en el método classList.toggle("color") aplicado sobre body.

La primera vez que se llama, añade el elemento body a la clase css "color", por lo que el navegador le aplica las propiedades de esa clase: pone el fondo azul.

La siguiente vez que se llame hace lo contrario: saca a body de la clase color, y el navegador aplica el estilo por defecto, que es sin color de fondo.

En esta animación se muestra en funcionamiento.

Al apretar la tecla ESPACIO cambia de color el fondo, entre blanco y azul claro.

Ejemplo 5: Detectando pulsaciones y liberaciones de teclas

Las teclas tienen asignado un nombre y un código, accesibles a través de las propiedades e.key y e.KeyCode.

Además de detectar cuándo se ha pulsado una tecla, también podemos detectar cuándo se ha liberado.

Esto nos será muy útil para un mejor control de la raqueta del videojuego retro.

En este ejemplo se muestra en un párrafo la información de la tecla pulsada: su nombre y su código, y se elimina en cuanto se libera.

Este es su funcionamiento:

  • Fichero HTML: Ej-05-teclas-2.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="Ej-05.js" defer></script>
    <title>Ejemplo 5: Teclas-2</title>
</head>
<body>
    <p>Pulsa una tecla</p>
    <p id="display"></p> 
</body>
</html>
  • *Fichero javascript: Ej-05.js
console.log("Ejecutando JS...");

const display = document.getElementById("display");

//-- Tecla pulsada: Mostrar su información
window.onkeydown = (e)=> {
  display.innerHTML = `Tecla: ${e.key}. Código: ${e.keyCode}`
}

//-- Tecla liberada: Borrar el párrafo
window.onkeyup = (e) => {
  display.innerHTML = ""
}

WooClap Time!

Sonidos

En HTML disponemos del elemento Audio que nos permite reproducir sonidos.

Típicamente usamos ficheros en algún formato de audio (Ej. mp3) que luego reproducimos desde nuestros programas en Javascript.

Los sonidos de las animaciones, o los asociados a eventos, suelen ser cortos.

Los pasos para reproducirlos cuando ocurre algún evento en javascript son los siguientes:

  1. Crear un elemento nuevo de Audio, inicializado con el fichero a reproducir
  2. Establecer la función de retrollamada del evento asociado a ese sonido (pulsación de una tecla, un botón, rebota de la pelota...)
  3. Para reproducir el sonido:
  • Poner la propiedad currenTime a 0 para que el sonido empiece a reproducirse desde el principio
  • Usar el método play() para comenzar la reproducción;

Ejemplo 6: Botones sonoros

Para probar haremos un programa con dos botones.

Al pulsarlos, cada uno emitirá un sonido obtenido de un fichero de audio (mp3).

Los ficheros de audio son los siguientes.

Descárgalos y colócalos en el mismo directorio donde esté el fichero html y el javascript.

En el fichero HTML simplemente se colocan los botones y se carga el javascript.

  • Fichero HTML: Ej-06-sonido-1.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="Ej-06.js" defer></script>
    <title>Ejemplo 6: Sonido 1</title>
</head>
<body>
    <p>Prueba de sonidos</p>
    <input type="button" id="click" value="Click">  
    <input type="button" id="what" value="What">  
</body>
</html>

Desde javascript obtenemos los botones y creamos dos objetos de audio a partir de los ficheros mp3.

  • Fichero javascript: Ej-06.js
console.log("Ejecutando JS...");

//--Obtener los botones
const click = document.getElementById("click")
const what = document.getElementById("what");

//-- Crear los elementos de sonido
const click_sound = new Audio('click.mp3');
const what_sound = new Audio('what.mp3');

click.onclick = () => {
  click_sound.currentTime = 0;
  click_sound.play();
}

what.onclick = () => {
  what_sound.currentTime = 0;
  what_sound.play();
}

Cada vez que se pulsa un botón se inicializa el tiempo a 0 (por si ya estuviese reproduciéndose el sonido) mediante el atributo currentTime y se llama al método play() para que suene.

Ejemplo 7: Rebotando con sonido

Vamos a hacer sonar los rebotes en las paredes.

Utilizando el ejemplo 13 de la sesión 6 de Animaciones, vamos a hacer que suene al rebotar en las paredes.

Con el html pintamos el canvas.

  • Fichero HTML: Ej-07-rebote-sonido-1.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="Ej-07.js" defer></script>
    <link rel="stylesheet" href="Ej-07.css">
    <title>Ejemplo 7: Rebote con Sonido</title>
</head>
<body>
    <h2>Canvas</h2>
    <canvas id="canvas"></canvas>
</body>
</html>

Utilizamos el css para dar estilos y visualizar el canvas.

  • Fichero css: Ej-07.css
/* Estilo del canvas
  Lo bordeamos con una línea negra y le damos fondo
  azul para distinguirlo
*/

canvas {
    background-color: lightblue;
    border-style: solid;
    border-width: 1px;
    border-color: black;
    border-radius: 5px;
  }

Por último, en el fichero javascript añadimos la pista de audio, y el código necesario para hacer que suene al rebotar en las paredes.

  • Fichero javascript: Ej-07.js
console.log("Ejecutando JS...");

const canvas = document.getElementById("canvas");

//-- Definir el tamaño del canvas
canvas.width = 300;
canvas.height = 100;

//-- Obtener el contexto del canvas
const ctx = canvas.getContext("2d");

//-- Coordenadas del objeto
let x = 0;
let y = 10;

//-- Velocidades del objeto
let velx = 3;
let vely = 1;

//-- Crear los elementos de sonido
const rebote_sound = new Audio('rebote.mp3');

//-- Función principal de animación
function update() 
{
  console.log("test");
  //-- Algoritmo de animación:
  //-- 1) Actualizar posición del  elemento
  //-- (física del movimiento rectilíneo uniforme)

   //-- Condición de rebote en extremos verticales del canvas
   if (x < 0 || x >= (canvas.width - 20) ) {
      rebote_sound.currentTime = 0;
      rebote_sound.play();
      velx = -velx;
  }

  //-- Condición de rebote en extremos horizontales del canvas
  if (y <= 0 || y > 80) {
    rebote_sound.currentTime = 0;
    rebote_sound.play();
    vely = -vely;
  }

  //-- Actualizar la posición
  x = x + velx;
  y = y + vely;

  //-- 2) Borrar el canvas
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  //-- 3) Dibujar los elementos visibles
  ctx.beginPath();
    ctx.rect(x, y, 20, 20);

    //-- Dibujar
    ctx.fillStyle = 'red';

    //-- Rellenar
    ctx.fill();

    //-- Dibujar el trazo
    ctx.stroke()
  ctx.closePath();

  //-- 4) Volver a ejecutar update cuando toque
  requestAnimationFrame(update);
}

//-- ¡Que empiece la función!
update();

Para el sonido del rebote puedes utilizar el siguiente fichero:

Introducción: Web Audio API

Pronto veremos la codificación multimedia, es decir, cómo se capturan los sonidos y se transforman en ceros y unos que podemos manipular digitalmente.

Por eso es un buen momento para hacer una introducción a la Web Audio API.

Una interfaz de programación de aplicaciones (API) que permite a los desarrolladores web crear y manipular audio en el navegador utilizando JavaScript.

Esta API proporciona una serie de herramientas para trabajar con audio en tiempo real, incluyendo la creación de gráficos de audio, síntesis de sonido, procesamiento de audio, efectos de audio, etc.

Estas son algunas de las herramientas que podemos utilizar.

AudioContext

La clase AudioContext es el punto de entrada principal para la API.

Representa un contexto de audio que se puede utilizar para crear y manipular nodos de audio.

Nodos de audio

La API proporciona una variedad de nodos de audio predefinidos, como AudioBufferSourceNode para la reproducción de archivos de audio, GainNode para ajustar el volumen, BiquadFilterNode para filtrar el audio, ConvolverNode para aplicar reverberación, entre otros.

Estos nodos se pueden conectar entre sí para crear cadenas de procesamiento de audio.

Síntesis de sonido

La API permite generar formas de onda de audio programáticamente utilizando osciladores (OscillatorNode), lo que facilita la creación de sonidos y efectos personalizados.

Procesamiento de audio

La Web Audio API permite procesar y manipular audio en tiempo real utilizando JavaScript.

Esto puede incluir efectos de sonido, análisis de audio en tiempo real, mezcla de audio y más.

Efectos de audio

La API proporciona varios nodos para aplicar efectos de audio, como reverberación, distorsión, delay, entre otros.

Esto permite a los desarrolladores crear experiencias de audio inmersivas y personalizadas en aplicaciones web.

Vamos a ver un ejemplo de cómo funciona.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sound Distortion</title>

    <script src="ej-01.js" defer></script>

</head>
<body>
    <input type="file" id="fileInput" accept="audio/*">
    <button id="playButton">Play</button>
    <button id="stopButton">Stop</button>
    <p>Distortion Level: <input type="range" id="distortionSlider" min="0" max="100" value="50"></p>
    <canvas id="distortionCurveCanvas" width="600" height="200"></canvas>
</body>
</html>
var audioContext = new (window.AudioContext || window.webkitAudioContext)();
var sourceNode = null;
var distortionNode = audioContext.createWaveShaper();
var gainNode = audioContext.createGain();

distortionNode.curve = makeDistortionCurve(0); // Initial distortion level
distortionNode.oversample = '4x';

// Load audio file
document.getElementById('fileInput').addEventListener('change', function(event) {
    var file = event.target.files[0];
    var reader = new FileReader();

    reader.onload = function(e) {
        var audioData = e.target.result;
        audioContext.decodeAudioData(audioData, function(buffer) {
            if (sourceNode) {
                sourceNode.stop();
                sourceNode.disconnect();
            }
            sourceNode = audioContext.createBufferSource();
            sourceNode.buffer = buffer;
            sourceNode.connect(distortionNode);
            distortionNode.connect(gainNode);
            gainNode.connect(audioContext.destination);
        });
    };

    reader.readAsArrayBuffer(file);
});

// Play audio
document.getElementById('playButton').addEventListener('click', function() {
    if (sourceNode) {
        sourceNode.start();
    }
});

// Stop audio
document.getElementById('stopButton').addEventListener('click', function() {
    if (sourceNode) {
        sourceNode.stop();
    }
});

// Change distortion level
document.getElementById('distortionSlider').addEventListener('input', function() {
    var distortionLevel = parseFloat(this.value);
    distortionNode.curve = makeDistortionCurve(distortionLevel);
    drawDistortionCurve();
});

// Function to create distortion curve
function makeDistortionCurve(amount) {
    var k = typeof amount === 'number' ? amount : 50;
    var numSamples = 44100;
    var curve = new Float32Array(numSamples);
    var deg = Math.PI / 180;
    var i = 0;
    var x;
    for (; i < numSamples; ++i) {
        x = i * 2 / numSamples - 1;
        curve[i] = (3 + k) * x * 20 * deg / (Math.PI + k * Math.abs(x));
    }
    return curve;
}

// Function to draw distortion curve
function drawDistortionCurve() {
    var canvas = document.getElementById('distortionCurveCanvas');
    var ctx = canvas.getContext('2d');
    var curve = distortionNode.curve;
    var width = canvas.width;
    var height = canvas.height;

    ctx.clearRect(0, 0, width, height);
    ctx.beginPath();
    ctx.moveTo(0, height / 2);

    for (var i = 0; i < curve.length; i++) {
        var x = (i / curve.length) * width;
        var y = ((curve[i] + 1) / 2) * height;
        ctx.lineTo(x, y);
    }

    ctx.strokeStyle = 'red';
    ctx.stroke();
}

// Draw initial distortion curve
drawDistortionCurve();

Puedes utilizar el siguiente archivo de audio o cualquier otro:

Find Your Way Beat - Nana Kwabena (mp3)

Este es el resultado:

Cambiando la distorsión con el deslizador, podemos dar al sonido un valor añadido, es como tocar un instrumento digital.

Elemento Vídeo

Los vídeos se insertan en nuestras páginas web utilizando la etiqueta <Video>.

Con los atributos width y height establecemos el tamaño del vídeo.

Con la etiqueta <source> se indica el fichero de vídeo.

Ejemplo 8: Autoreproducción de un vídeo

Con atributo autoplay el vídeo comenzará a reproducirse al cargar la página (El vídeo usado está aquí: robot.mp4)

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ejemplo 8: Video 1</title>
</head>
<body>
    <h2>Vídeo</h2>
    <video width="300" height="200" autoplay>
      <source src="robot.mp4">
     </video>
    <p>Vídeo con autoplay. Al cargar la página arranca</p>  
</body>
</html>

En el navegador vemos esto:

Al cargar la página, o recargarla se activa el vídeo.

En esta animación lo vemos en acción:

Ejemplo 9: Vídeo con controles

Introduciendo el atributo controls dentro de la etiqueta vídeo, nos aparecen unos controles básicos para manejar el vídeo: play/pause, control de volumen, línea de tiempo, etc...

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ejemplo 9: Video 2</title>
</head>
<body>
    <h2>Vídeo</h2>
    <video width="300" height="200" controls>
      <source src="robot.mp4" type="video/mp4">
     </video>
    <p>Vídeo con controles</p>
</body>
</html>

Este es el aspecto que tienen los controles en el navegador:

Y en esta animación se muestran en acción:

Ejemplo 10: Control desde javascript

Los elementos de tipo vídeo también incluyen una api de javascript para modificar sus propiedades e interaccionar con ellos.

Esto nos permite definir nuestros propios controles.

En este ejemplo definimos 4 botones: uno para reproducir/detener, dos para cambiar el tamaño del vídeo, y uno para ir al segundo 2.

El HTML es el siguiente:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="Ej-10.js" defer></script>
    <title>Ejemplo 10: Video 3</title>
</head>
<body>
    <h2>Vídeo</h2>
    <p>Control desde Javascript</p>
    <video width="300" height="200" id="video">
      <source src="robot.mp4" type="video/mp4">
     </video>
     <br>
  <button type="button" id="play">Play/Stop</button>
  <button type="button" id="big">Big</button>
  <button type="button" id="small">Small</button>
  <button type="button" id="time2">Time 0:2</button>
</body>
</html>

En el fichero javascript leemos los elementos de interfaz.

El vídeo lo situamos en el objeto vídeo, y sobre el que actuamos.

Los métodos usados son:

  • play(): Reproducir el vídeo
  • pause(): Detener el vídeo

Y las propiedades usadas son:

  • width: anchura del vídeo

  • height: Altura del vídeo

  • currentTime: Tiempo actual del vídeo (por donde va la reproducción)

  • paused: Indica si el vídeo está pausado o no

  • Fichero javascript: Ej-10.js

console.log("Ejecutando JS...");

const video = document.getElementById("video");
const play = document.getElementById("play");
const big = document.getElementById("big");
const small = document.getElementById("small");
const time = document.getElementById("time2");

play.onclick = () => {
 if (video.paused)
   video.play()
 else {
   video.pause()
 }
}

big.onclick = () => {
 video.width = 500;
 video.height = 300;
}

small.onclick = () => {
 video.width = 300;
 video.height = 200;
}

time.onclick = () => {
 video.currentTime = 2;
}

Al verlo en el navegador nos aparece esto:

Y en esta animación lo vemos en funcionamiento:

Youtube

Para incluir vídeo de youtube en nuestras páginas html, utilizamos la etiqueta iframe.

Con el atributo src indicamos la URL del vídeo de youtube, pero con un formato diferente:

https://www.youtube.com/embed/identificador-youtube

Hay que indicar /embed y a continuación el identificador del vídeo en youtube.

Ejemplo 11: Reproduciendo un vídeo de youtube

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="Ej-10.js" defer></script>
    <title>Ejemplo 11: Youtube</title>
</head>
<body>
    <h2>Vídeo Youtube</h2>

    <iframe width="420" height="315"
       src="https://www.youtube.com/embed/fLjjrJ7bun8">
   </iframe>
   <p>Vídeo en youtube</p>
</body>
</html>

En el navegador se muestra de la siguiente manera:

Y en esta animación se muestra en funcionamiento:

Consideraciones de accesibilidad para el video

Es importante tener en cuenta la accesibilidad para garantizar que el contenido multimedia sea accesible para todos los usuarios, incluyendo aquellos con discapacidades.

Estas son algunas consideraciones específicas sobre la accesibilidad al trabajar con la reproducción de vídeo:

Transcripciones y subtítulos

Proporciona transcripciones de audio y subtítulos para los vídeos.

Esto beneficia a personas con discapacidades auditivas o aquellas que prefieren leer el contenido en lugar de escucharlo.

Descripciones de vídeo

Para usuarios con discapacidades visuales, es esencial proporcionar descripciones de vídeo (audio descripciones) que describen visualmente lo que está sucediendo en el vídeo, incluyendo acciones, movimientos y cambios visuales importantes.

Controles de reproducción accesibles

Asegúrate de que los controles de reproducción del vídeo sean accesibles para usuarios que dependen de un teclado en lugar de un ratón.

Esto implica asegurarse de que los controles puedan ser activados y utilizados fácilmente con el teclado y que se proporcione atajos de teclado claros y consistentes.

Contraste y tamaño de texto

Si estás proporcionando controles personalizados para el vídeo, asegúrate de que el texto y los iconos sean lo suficientemente grandes y tengan un contraste adecuado para ser legibles para usuarios con discapacidades visuales.

Compatibilidad con lectores de pantalla

Asegúrate de que tu reproductor de vídeo sea compatible con lectores de pantalla para que los usuarios con discapacidades visuales puedan acceder a los controles y al contenido del vídeo de manera efectiva.

Proporcionar alternativas

Si tu aplicación utiliza vídeos para transmitir información importante, proporciona una alternativa accesible, como texto descriptivo o imágenes estáticas con texto explicativo, para usuarios que no pueden acceder al contenido de vídeo.

Pruebas de accesibilidad

Realiza pruebas de accesibilidad en tu aplicación utilizando herramientas de evaluación de accesibilidad y obteniendo retroalimentación de usuarios con diversas discapacidades para identificar y abordar cualquier problema de accesibilidad en la reproducción de vídeo.

En este enlace podéis encontrar una lista completa de aplicaciones online para probar la accesibilidad.

Web Accessibility Evaluation Tools List

Si tenemos en cuenta estas pautas de accesibilidad al desarrollar aplicaciones web con reproducción de vídeo, podemos garantizar que tu contenido multimedia sea accesible para todos los usuarios, independientemente de sus capacidades o limitaciones.

Autor

Jesús Parrado Alameda (jesusgpa)

Creditos

Licencia

Enlaces

⚠️ **GitHub.com Fallback** ⚠️