Realizarea unei tastaturi de pian redabile poate fi o modalitate excelentă de a învăța un limbaj de programare (în afară de a fi o grămadă de distracție). Acest tutorial vă arată cum să codificați unul folosind vanilla JavaScript fără a fi nevoie de biblioteci sau cadre externe.
Aici este Tastatură pian JavaScript Am făcut dacă doriți să verificați mai întâi produsul final.
Acest tutorial presupune că aveți o înțelegere de bază a JavaScript-ului, cum ar fi funcțiile și gestionarea evenimentelor, precum și familiarizarea cu HTML și CSS. În caz contrar, este complet prietenos pentru începători și orientat către cei care doresc să-și îmbunătățească abilitățile JavaScript prin învățarea bazată pe proiecte (sau pur și simplu doresc să facă un proiect mișto!).
Tastatura de pian pe care o realizăm pentru acest proiect se bazează pe tastatură sintetică generată dinamic realizat de Keith William Horwood. Vom extinde numărul de taste disponibile la 4 octave și vom seta noi legături de taste.
Deși tastatura sa poate reda sunete din alte instrumente, vom păstra lucrurile simple și vom rămâne doar cu pianul.
Iată pașii pe care îi vom face pentru a aborda acest proiect:
1. Obțineți fișiere de lucru
2. Configurați legăturile de taste
3. Generați tastatura
4. Manipulați apăsările de taste
Să începem!
1. Obțineți fișiere de lucru
Acest tutorial va utiliza următoarele fișiere:
După cum am menționat, ne vom baza tastatura de pian pe cea realizată de Keith. Bineînțeles, vom împrumuta, de asemenea, o parte din codul său, pe care el a permis-o cu amabilitate cu audiosynth.js.
Încorporăm audiosynth.js în playKeyboard.js (versiunea mea modificată a unora dintre codurile lui Keith) care gestionează toate JavaScript-urile noastre. Acest tutorial oferă o explicație detaliată în secțiunile următoare despre principalele puncte ale modului în care codul din acest fișier creează o tastatură de pian complet funcțională.
Lăsăm neatins fișierul audiosynth.js, deoarece este singurul responsabil pentru generarea sunetului.
Codul din acest fișier distinge această tastatură de pian de altele găsite online prin utilizarea Javascript pentru a genera dinamic sunetul adecvat atunci când utilizatorul apasă o tastă. Astfel, codul nu trebuie să încarce niciun fișier audio extern.
Keith oferă deja o explicație a modului în care funcționează generația de sunet pe site-ul său, astfel încât să nu intrăm în detalii aici.
Pe scurt, implică utilizarea Math.sin()
funcționează în JS pentru a crea forme de undă sinusoidale și a le transforma astfel încât să sune mai mult ca instrumente reale, prin niște matematici fanteziste.
Creați un fișier HTML index și să conectăm la fișierele JS din antet:
<script src="audiosynth.js"></script>
<script src="playKeyboard.js"></script>
În corp, putem crea un gol <div>
element care să ne servească drept „container” de la tastatură:
<div id= “keyboard”></div>
Îi dăm un nume de identificare, astfel încât să îl putem referi mai târziu atunci când creăm tastatura folosind JS. Putem rula codul nostru JS apelându-l și în corp:
<script type="text/javascript">playKeyboard()</script>
Folosim playKeyboard.js ca o funcție importantă. Va rula imediat ce browserul ajunge la acea linie de cod și va genera o tastatură complet funcțională în <div>
element cu
id = “keyboard”
.
Primele linii ale playKeyboard.js se configurează pentru funcționalitatea dispozitivelor mobile (opțional) și creează o nouă AudioSynth()
obiect. Folosim acest obiect pentru a apela metodele audiosynth.js la care am legat anterior. Folosim una dintre aceste metode la început pentru a seta un volum pentru sunet.
Pe linia 11, setăm poziția mijlocului C la a 4-a octavă.
2. Configurați legăturile de taste
Înainte de a genera tastatura, ar trebui să configurăm legăturile de taste, deoarece acestea determină câte taste ar trebui generate.
Am vrut inițial să încerc să cânt notele de deschidere ale „Für Elise”, așa că am ales o gamă de 4 octave pentru un total de 48 de taste alb-negru. Acest lucru necesită aproape fiecare tastă de pe tastatura mea (PC) și vă puteți simți liber să includeți mai puține.
O notă de avertisment: nu am cele mai bune legături de taste, astfel încât acestea să se simtă neintuitive atunci când încercați să jucați. Poate că acesta este prețul încercării de a crea o tastatură de 4 octave.
Pentru a configura legăturile de taste, creați mai întâi un obiect care va utiliza codul cheie ca chei și nota care va fi redată ca valori ale cheii (linia de pornire 15):
var keyboard = {
/* ~ */
192: 'C,-2',
/* 1 */
49: 'C#,-2',
/* 2 */
50: 'D,-2',
/* 3 */
51: 'D#,-2',
//...and the rest of the keys
}
Comentariile indică tastele pe care un utilizator le poate apăsa pe tastatura computerului. Dacă un utilizator apasă tasta tilde, atunci codul cheie corespunzător este 192. Puteți obține codul cheie folosind un instrument precum keycode.info.
Valoarea cheie este nota care trebuie redată și scrisă în formatul „notă, modificator de octavă”, unde modificatorul de octavă reprezintă poziția relativă a octavei din octava care conține mijlocul C. De exemplu, „C, -2” este nota C 2 octave sub mijlocul C.
Rețineți că nu există taste „plate”. Fiecare notă este reprezentată de un „ascuțit”.
Pentru a face tastatura noastră de pian funcțională, trebuie să pregătim un tabel de căutare inversă unde comutăm key: value
perechi astfel încât nota care urmează să fie redată devine cheia și codul cheie devine valoarea.
Avem nevoie de un astfel de tabel pentru că vrem să repetăm notele muzicale pentru a ne genera cu ușurință tastatura.
Acum, aici lucrurile pot deveni complicate: avem de fapt nevoie de 2 tabele de căutare inversă.
Folosim un tabel pentru a căuta eticheta pe care dorim să o afișăm pentru tasta computerului pe care o apăsăm pentru a reda o notă (declarată ca reverseLookupText
pe linia 164) și o secundă pentru a căuta tasta efectivă care a fost apăsată (declarată ca reverseLookup
pe linia 165).
Inteligenții își pot da seama că ambele tabele de căutare au coduri de chei ca valori, deci care este diferența dintre ele?
Se pare că (din motive necunoscute mie) când primești un cod cheie care corespunde unei chei și încerci să îl folosești String.fromCharCode()
pe acel cod de cheie, nu întotdeauna reveniți la același șir reprezentând tasta apăsată.
De exemplu, apăsarea parantezei deschise la stânga dă codul cheie 219, dar când încercați efectiv să convertiți codul cheie înapoi într-un șir, String.fromCharCode(219)
returnează „Û”. A obține “[“, you have to use key code 91. We replace the incorrect codes starting on line 168.
Getting the right keycode initially involved a bit of trial and error, but later I realized you can just use another function (getDispStr()
on line 318) to force the correct string to be displayed.
The majority of the keys do behave properly but you can choose to start with a smaller keyboard so you don’t have to deal with incorrect keycodes.
3. Generate Keyboard
We start the keyboard generation process by selecting our <div>
element keyboard container with document.getElementById(‘keyboard’)
on line 209.
On the next line, we declare the selectSound
object and set the value
property to zero to have audioSynth.js load the sound profile for piano. You may wish to enter a different value (can be 0-3) if you want to try out other instruments. See line 233 of audioSynth.js with Synth.loadSoundProfile
for more details.
On line 216 with var notes
, we retrieve the available notes for one octave (C, C#, D…B) from audioSynth.js.
We generate our keyboard by looping through each octave and then each note in that octave. For each note, we create a <div>
element to represent the appropriate key using document.createElement(‘div’)
.
To distinguish whether we need to create a black or white key, we look at the length of the note name. Adding a sharp sign makes the length of the string greater than one (ex. ‘C#’) which indicates a black key and vice versa for white.
For each key we can set a width, height, and an offset from the left based on key position. We can also set appropriate classes for use with CSS later.
Next, we label the key with the computer key we need to press to play its note and store it in another <div>
element. This is where reverseLookupText
comes in handy. Inside the same <div>
, we also display the note name. We accomplish all of this by setting the label’s innerHTML property and appending the label to the key (lines 240-242).
label.innerHTML = '<b class="keyLabel">' + s + '</b>' + '<br /><br />' + n.substr(0,1) +
'<span name="OCTAVE_LABEL" value="' + i + '">' + (__octave + parseInt(i)) + '</span>' +
(n.substr(1,1)?n.substr(1,1):'');
Similarly, we add an event listener to the key to handle mouse clicks (line 244):
thisKey.addEventListener(evtListener[0], (function (_temp) {return function () {fnPlayKeyboard ({keyCode: _temp});}}) (reverseLookup[n + ',' + i]));
Primul parametru evtListener[0]
este o mousedown
eveniment declarat mult mai devreme pe linia 7. Al doilea parametru este o funcție care returnează o funcție. Avem nevoie reverseLookup
pentru a ne obține codul cheie corect și trecem acea valoare ca parametru _temp funcției interioare. Nu vom avea nevoie de reverseLookup pentru a face față realității keydown
evenimente.
Acest cod este pre-ES2015 (alias ES6) și echivalentul actualizat, sperăm mai clar, este:
const keyCode = reverseLookup[n + ',' + i];
thisKey.addEventListener('mousedown', () => {
fnPlayKeyboard({ keyCode });
});
După crearea și adăugarea tuturor tastelor necesare la tastatura noastră, va trebui să ne ocupăm de redarea efectivă a unei note.
4. Manipulați apăsările de taste
Gestionăm apăsările de taste în același mod, indiferent dacă utilizatorul dă clic pe tastă sau apasă tasta corespunzătoare a computerului prin utilizarea funcției fnPlayKeyboard
pe linia 260. Singura diferență este tipul de eveniment pe care îl folosim addEventListener
pentru a detecta apăsarea tastei.
Am creat o matrice numită keysPressed
în linia 206 pentru a detecta ce taste sunt apăsate / făcute clic. Pentru simplitate, vom presupune că o tastă apăsată poate include și ea făcând clic pe ea.
Putem împărți procesul de gestionare a apăsărilor de taste în 3 pași: adăugarea codului cheie al tastei apăsate keysPressed
, redarea notei corespunzătoare și eliminarea codului cheie din keysPressed
.
Primul pas al adăugării unui cod cheie este ușor:
keysPressed.push(e.keyCode);
Unde e
este evenimentul detectat de addEventListener
.
Dacă codul cheie adăugat este una dintre legăturile cheie pe care le-am atribuit, atunci apelăm fnPlayNote()
pe linia 304 pentru a reda nota asociată acelei taste.
În fnPlayNote()
, mai întâi creăm un nou Audio()
element container
pentru nota noastră folosind generate()
metoda din audiosynth.js. Când sunetul se încarcă, putem reda nota.
Liniile 308-313 sunt cod vechi și par că pot fi doar înlocuite cu container.play()
, deși nu am făcut niciun test extins pentru a vedea care este diferența.
Îndepărtarea unei apăsări pe tastă este, de asemenea, destul de simplă, deoarece puteți scoate doar cheia din keysPressed
matrice cu splice
metoda de pe linia 298. Pentru mai multe detalii, consultați funcția numită fnRemoveKeyBinding()
.
Singurul lucru pe care trebuie să-l urmărim este atunci când utilizatorul ține apăsată o cheie sau mai multe taste. Trebuie să ne asigurăm că nota se redă o singură dată în timp ce o tastă este apăsată (rândurile 262-267):
var i = keysPressed.length;
while(i--) {
if(keysPressed[i]==e.keyCode) {
return false;
}
}
Revenind false
previne restul fnPlayKeyboard()
de la executare.
rezumat
Am creat o tastatură de pian complet funcțională folosind JavaScript vanilat!
Pentru a recapitula, iată pașii pe care i-am făcut:
-
Am configurat fișierul nostru index HTML pentru a încărca fișierele JS corespunzătoare și a le executa
playKeyboard()
în<body>
pentru a genera și a face tastatura funcțională. Noi avem o<div>
element cuid= "keyboard"
unde va fi afișată tastatura pe pagină. -
În fișierul nostru JavaScript playKeyboard.js, ne-am configurat legăturile de chei cu chei de coduri ca chei și note muzicale ca valori. De asemenea, creăm două tabele de căutare inversă în care unul este responsabil pentru căutarea etichetei cheii corespunzătoare bazată pe notă, iar cealaltă pentru căutarea codului cheie corect.
-
Generăm dinamic tastatura, parcurgând fiecare notă din fiecare gamă de octave. Fiecare cheie este creată ca a sa
<div>
element. Folosim tabelele de căutare inversă pentru a genera eticheta cheii și codul cheie corect. Apoi un ascultător de evenimente activatmousedown
îl folosește pentru a apelafnPlayKeyboard()
pentru a cânta nota.
keydown
evenimentul apelează aceeași funcție, dar nu are nevoie de un tabel de căutare inversă pentru a obține codul cheie. -
Ne ocupăm de apăsarea tastelor rezultate fie din clicurile mouse-ului, fie de apăsarea tastelor computerului în 3 pași: adăugăm codul cheie al tastei apăsate într-o matrice, redăm nota corespunzătoare și eliminăm codul cheie din matricea respectivă. Trebuie să fim atenți să nu redăm în mod repetat o notă (de la început) în timp ce utilizatorul ține apăsată continuu o tastă.
Tastatura este acum complet funcțională, dar poate părea puțin anostă. Vă voi lăsa partea CSS?
Din nou, aici este Tastatură pian JavaScript Am făcut pentru referință.
Dacă doriți să aflați mai multe despre dezvoltarea web și să consultați alte proiecte îngrijite, vizitați blogul meu la 1000 Mile World.
Mulțumim pentru lectură și codificare fericită!