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
clickString
y el argumento que será cada cuerdathisString
. - Añadimos la clase
imgTitle
al título para encenderlo. - Nos aseguramos de que el botón solo tiene la clase
string
, para evitar duplicar clases. - Usamos el atributo
id
del botón para seleccionar el sonido de la cuerda elegida mediante el objetowindow
y lo detenemos al inicio del sonido concurrentTime
. - Reproducimos el sonido con el método
play()
. - Creamos la variable
thisNote
para encender las notas. - Le añadimos la clase
playingSound
al botón de la cuerda que está sonando, para encenderla. - Le añadimos la clase
lightOn
a 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
playingSound
a la cuerda, para apagarla. - – Cambiamos la clase
lightOn
porlightOff
a la nota, para apagarla. - – Condicional if: Si no hay ningún elemento con la clase
playingSound
: - – Quitamos la clase
imgTitle
al título, para apagarlo. - – Cierre de if linea 13
- – Cierre de if linea 10
- Ejecutamos el contenido del método
setTimeOut
4 segundos y medio después de llamarlo (cuando el sonido ha dejado de sonar). - Cierre de la función
clickString
linea 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
imgTitle
del título para apagarlo. - Detenemos todos los sonidos con el método
pause()
. - Creamos la variable
auxString
que 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
playingSound
a 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.