Afinador de Guitarra – Online Guitar Tuner – v2
Hace unos años hice un Afinador de Guitarra Online en Flash para la web de Liyonel Guitars.
Flash va a morir, de hecho está agonizando ya… en el año 2016 estuvo presente solo en el 10% de las webs y a partir de 2017 Firefox y Chrome empezarán a bloquear el contenido Flash.
Por eso, pensé en hacer un nuevo afinador en HTML5, con algo de CSS3 y con Javascript nativo (para evitar la carga de librerías externas).
La idea original era usar canvas para las animaciones, pero lo dejaremos para la siguiente versión y aquí las haremos con CSS y Javascript.
HTML
El HTML se divide en tres partes para las que usaremos elementos de HTML5 :
header
Aqui pondremos el titulo que iluminaremos con CSS3 cuando suene alguna cuerda, para ello añadiremos con Javascript una clase extra al elemento h1 modificando sus estilos CSS.
<header>
<h1 id="title">Online Guitar Tuner</h1>
</header>
section
En esta sección van las cuerdas que serán elementos button , también hemos puesto las notas que se iluminarán al tocar cada cuerda. Igualmente con Javascript añadiremos una clase extra a cada elemento para modificar su CSS y aplicar el efecto de iluminado al tocar las cuerdas.
<section id="guitarBody">
<button id="s6" onclick="clickString(this.id)"></button>
<!-- un button para cada cuerda -->
<div class="notes">
<span id="s6Note">E<span class="notas">MI</span></span>
<!-- un span para cada cuerda -->
</div>
</section>
footer
En la última parte vamos a poner los controles del afinador; un botón para detener el sonido, otro botón para mantener el sonido, y la púa que hará que suenen las cuerdas onmouseover.
<footer>
<button onclick="stopStrings()" id="btnStop">STOP</button>
<button onclick="usePick()" id="btnPick">PICK</button>
<button onclick="holdSound()" id="btnHold">HOLD</button>
</footer>
CSS / CSS3
Lo único destacable de lo estilos, más allá de imágenes de fondo y posiciones de los elementos, es el iluminado de las notas y el efecto metalizado del texto.
Iluminado de notas
Muy simple, con las propiedades color y text-shadow combinadas con la propiedad transition:
.notes span {
width: 50px;
display: inline-block;
color: #171717;
text-align: center;
font-size: 50px;
z-index: 0;
text-shadow: -1px -1px 1px #000000, 0px 0px 1px #6f6f6f;
}
.notes span.lightOn {
color: #71abeb;
text-shadow: 0px 0px 15px #3779c5, 0px 0px 25px #3779c5, 0px 0px 35px #71abeb, -1px -1px 1px #000000, 0px 0px 1px #6f6f6f;
transition: all 0.2s ease;
}
Efecto metalizado del texto
Algo más elaborado, pero muy fácil tambien, la clave está en las propiedades color, background-color, background-clip y text-shadow.
Para aplicar el efecto de iluminado basta con cambiar las propiedaes background-color y text-shadow en el selector :hover, o añadiendo al elemento una clase con Javascript como en este caso:
h1 {
margin: 0.5vh 0;
font-size: 2em;
padding: 3vh 0;
background-color: #333333;
-webkit-background-clip: text;
-moz-background-clip: text;
background-clip: text;
color: transparent;
text-shadow: rgba(255,255,255,0.5) 0px 1px 3px;
}
h1.imgTitle{
text-shadow: 0 0 25px rgba(20, 139, 255, 0.8), 0 0 15px rgba(30, 144, 255, 0.54);
background-color: rgba(77, 134, 189, 0.8);
}
Javascript
El Javascript son solo un puñado de variables y algunas funciones:
Variables
Creamos seis variables para almacenar los sonidos de las cuerdas:
var s1 = new Audio('../audio/s1.mp3');
var s2 = new Audio('../audio/s2.mp3');
var s3 = new Audio('../audio/s3.mp3');
var s4 = new Audio('../audio/s4.mp3');
var s5 = new Audio('../audio/s5.mp3');
var s6 = new Audio('../audio/s6.mp3');
Después podremos acceder a cada sonido para reproducirlo o detenerlo usando el método window.
Funciones
Los nombres de las funciones son bastante descriptivos, lo que hacen básicamente es reproducir o detener los sonidos y añadir o quitar clases a elementos dependiendo de las cuerdas que toquemos, con ello cambiamos los estilos de los elementos para, por ejemplo, iluminarlos, y para ello usamos los métodos getElementById y querySelectorAll.
getElementById
Como vamos a usar bastante el método getElementById lo podemos acortar en una función, y pasar de esto:
document.getElementById('id');
A esto otro:
elem(id);
Con esta simple función:
function elem(id){
var element = document.getElementById(id);
return element;
}
En el resto de funciones usaremos nuestra función elem() acortando el código resultante.
Que suenen las cuerdas…
Una de las funciones clave es clickString que se activará al tocar una cuerda, y funciona de la siguiente manera:
En el HTML se le pasa como argumento el valor del atributo id de la cuerda que se ha tocado:
<button onclick="clickString(this.id)" class="string" id="s6"></button>
La función identifica la cuerda y hace el resto:
function clickString(thisString) {
elem('title').className='imgTitle';
elem(thisString).className = "string";
window[thisString].currentTime = 0;
window[thisString].play();
var thisNote = thisString+"Note";
elem(thisString).className = "string playingSound";
elem(thisNote).className = "lightOn";
setTimeout(function(){
if(window[thisString].loop != true){
elem(thisString).className = "string";
elem(thisNote).className = "lightOff";
if(document.querySelectorAll('.playingSound').length==0){
elem('title').className='';
}
}
}, 4500);
}
La función, explicada línea a línea, trabaja de la siguiente manera:
- Nombre de la función
clickStringy el argumento que será cada cuerdathisString. - Añadimos la clase
imgTitleal título para encenderlo. - Nos aseguramos de que el botón solo tiene la clase
string, para evitar duplicar clases. - Usamos el atributo
iddel botón para seleccionar el sonido de la cuerda elegida mediante el objetowindowy lo detenemos al inicio del sonido concurrentTime. - Reproducimos el sonido con el método
play(). - Creamos la variable
thisNotepara encender las notas. - Le añadimos la clase
playingSoundal botón de la cuerda que está sonando, para encenderla. - Le añadimos la clase
lightOna la nota de la cuerda que está sonando, para encenderla. - Llamamos al método
setTimeout, que se ejecutará 4 segundos y medio después… - – Condicional if: Si el sonido no está en bucle:
- – Quitamos la clase
playingSounda la cuerda, para apagarla. - – Cambiamos la clase
lightOnporlightOffa la nota, para apagarla. - – Condicional if: Si no hay ningún elemento con la clase
playingSound: - – Quitamos la clase
imgTitleal título, para apagarlo. - – Cierre de if linea 13
- – Cierre de if linea 10
- Ejecutamos el contenido del método
setTimeOut4 segundos y medio después de llamarlo (cuando el sonido ha dejado de sonar). - Cierre de la función
clickStringlinea 1
querySelectorAll
El método querySelectorAll devuelve, en una lista de nodos, todos los elementos del documento que tienen un determinado selector CSS. Se puede acceder a estos nodos mediante números de índice. De manera que:
document.querySelectorAll(".notas");
Nos devolverá una lista de elementos con la clase notas:
[span.notas, span.notas, span.notas, span.notas, span.notas, span.notas]
Y podemos acceder a ellos mediante números de índice:
var elemNotas = document.querySelectorAll('.notas');
elemNotas[0].className='primera';
elemNotas[1].className='segunda';
// uno para cada nota...
Que paren las cuerdas…
La función stopStrings funciona con el método querySelectorAll :
function stopStrings(){
elem('title').className='';
s1.pause(); s2.pause(); s3.pause(); s4.pause(); s5.pause(); s6.pause();
var auxString = document.querySelectorAll('.playingSound');
for (var x in auxString) {
if(auxString[x]!==undefined){
auxString[x].className = "string";
}
}
var auxNote = document.querySelectorAll(".lightOn");
for (x in auxNote) {
if(auxNote[x]!==undefined){
auxNote[x].className = "lightOff";
}
}
}
La función, explicada línea a línea, trabaja de la siguiente manera:
- Nombre de la función
stopStrings: - Quitamos la clase
imgTitledel título para apagarlo. - Detenemos todos los sonidos con el método
pause(). - Creamos la variable
auxStringque almacena las cuerdas que están sonando. - Con un bucle for recorremos la variable:
- – Condicional if: Si la variable, con su índice, está definida: (esto es para evitar errores en firefox)
- – Quitamos la variable
playingSounda cada elemento que la tenga, apagándolo. - – Cierre de if linea 6
- Cierre de for linea 5
- Repetimos el proceso para apagar las notas buscando los elementos con la clase
lightOn…
Demo
Es posible experimentar errores al mostar el código en la demo, es por el ancho del blog que todo a la vez no cabe… ya que el afinador necesita un mínimo de 320 pixels de ancho…
See the Pen Online Guitar Tuner by Josetxu (@josetxu) on CodePen.
En Codepen podéis ver la demo a tamaño completo.
Tetris Arcade Game - Atari 1988
Mas Toggle Switches con CSS
Fenómenos Meteorológicos con PUG y SASS
Live Coding Videos
Selector de color
Fuentes de Google
Soporte por navegadores
Manipulación de imágenes
Editor de código
Validador de código
Gráficas en Javascript