Kaip sukurti fortepijono klaviatūrą naudojant „Vanilla JavaScript“

Padaryti grojamą fortepijono klaviatūrą gali būti puikus būdas išmokti programavimo kalbos (be to, kad tai daugybė linksmybių). Šioje pamokoje parodoma, kaip koduoti naudojant „vanilla JavaScript“, nereikia jokių išorinių bibliotekų ar rėmų.

Čia yra mano sukurta „JavaScript“ fortepijono klaviatūra, jei norite pirmiausia patikrinti galutinį produktą.

Šioje pamokoje daroma prielaida, kad jūs iš esmės suprantate „JavaScript“, pvz., Funkcijas ir įvykių valdymą, taip pat esate susipažinę su HTML ir CSS. Priešingu atveju jis yra visiškai draugiškas pradedantiesiems ir skirtas tiems, kurie nori tobulinti savo „JavaScript“ įgūdžius mokydamiesi projektu (arba tiesiog nori sukurti šaunų projektą!).

Fortepijono klaviatūra, kurią gaminame šiam projektui, yra pagrįsta dinamiškai sukurta sintetine klaviatūra, kurią pagamino Keithas Williamas Horwoodas. Mes išplėsime galimų raktų skaičių iki 4 oktavų ir nustatysime naujus raktų susiejimus.

Nors jo klaviatūra gali atkurti kitų instrumentų garsus, mes viską paliksime paprastus ir tiesiog laikysimės pianino.

Štai žingsniai, kurių imsimės įgyvendindami šį projektą:

1. Gaukite darbo failus

2. Nustatykite klavišų susiejimus

3. Generuoti klaviatūrą

4. Tvarkykite klavišų paspaudimus

Pradėkime!

1. Gaukite darbo failus

Šioje mokymo programoje bus naudojami šie failai:

· Audiosynth.js

· PlayKeyboard.js

Kaip jau minėta, fortepijono klaviatūrą mes grįšime nuo tos, kurią sukūrė Keithas. Natūralu, kad mes taip pat pasiskolinsime dalį jo kodo, kuriam jis maloniai davė leidimą su audiosynth.js.

Mes įtraukiame audiosynth.js į „playKeyboard.js“ (mano modifikuota kai kurių Keitho kodo versija), kuri tvarko visą mūsų „JavaScript“. Šioje pamokoje tolesniuose skyriuose pateikiamas išsamus paaiškinimas apie pagrindinius dalykus, kaip šiame faile pateiktas kodas sukuria visiškai veikiančią pianino klaviatūrą.

Mes paliekame failą audiosynth.js nepaliestą, nes jis atsakingas tik už garso generavimą.

Šio failo kodas atskiria šią fortepijono klaviatūrą nuo kitų, rastų internete, naudodamas „Javascript“, kad dinamiškai generuotų reikiamą garsą, kai vartotojas paspaudžia klavišą. Taigi, kodas neturi įkelti jokių išorinių garso failų.

Keithas savo svetainėje jau pateikia paaiškinimą, kaip veikia garso generavimas, todėl čia nesigilinsime.

Trumpai tariant, tai apima Math.sin()JS funkcijos naudojimą kuriant sinusines bangų formas ir jas transformuojant, kad jie skambėtų labiau kaip tikri instrumentai per tam tikrą išgalvotą matematiką.

Sukurkite indekso HTML failą ir susiekime JS failus antraštėje:

Kūne galime sukurti tuščią elementą, kuris būtų klaviatūros „konteineris“:

Mes suteikiame jam id vardą, kad galėtume jį nurodyti vėliau, kai sukursime klaviatūrą naudodami JS. Mes galime paleisti savo JS kodą taip pat iškviesdami jį į kūną:

playKeyboard()

Kaip vieną didelę funkciją naudojame „playKeyboard.js“. Jis bus paleistas iškart, kai naršyklė pasieks tą kodo eilutę, ir su elementu sugeneruos visiškai veikiančią klaviatūrą

id = “keyboard”.

Pirmosiose „playKeyboard.js“ eilutėse nustatoma mobiliojo įrenginio funkcija (nebūtina) ir sukuriamas naujas AudioSynth()objektas. Šį objektą naudojame vadindami audiosynth.js metodus, kuriuos susiejome anksčiau. Norėdami nustatyti garso garsumą, pradžioje naudojame vieną iš šių metodų.

11 eilutėje nustatėme vidurio C padėtį iki 4 oktavos.

2. Nustatykite klavišų įrišimus

Prieš generuodami klaviatūrą, turėtume nustatyti klavišų susiejimus, nes jie nustato, kiek klavišų turėtų būti sukurta.

Iš pradžių norėjau pabandyti paleisti „Für Elise“ pradines natas, todėl pasirinkau 4 oktavų diapazoną, iš viso 48 juodus ir baltus klavišus. Tam reikėjo beveik kiekvieno mano (kompiuterio) klaviatūros klavišo ir galite drąsiai įtraukti mažiau.

Įspėjamoji pastaba: neturiu geriausių klavišų įrišimų, todėl jie gali jaustis neprotingi, kai jūs iš tikrųjų bandote groti. Galbūt tai yra bandymo sukurti 4 oktavų klaviatūrą kaina.

Norėdami nustatyti klavišų susiejimus, pirmiausia sukurkite objektą, kuris kaip raktus naudos raktų kodą, o pastaba, kurią grosite, kaip pagrindines reikšmes (15 pradinė eilutė):

var keyboard = { /* ~ */ 192: 'C,-2', /* 1 */ 49: 'C#,-2', /* 2 */ 50: 'D,-2', /* 3 */ 51: 'D#,-2', //...and the rest of the keys } 

Komentarai žymi klavišus, kuriuos vartotojas gali paspausti kompiuterio klaviatūroje. Jei vartotojas paspaudžia „tilde“ klavišą, atitinkamas raktų kodas yra 192. Raktų kodą galite gauti naudodami tokį įrankį kaip „keycode.info“.

Pagrindinė reikšmė yra nata, kurią reikia groti ir parašyti „natos, oktavos modifikatoriaus“ formatu, kur oktavos modifikatorius reiškia santykinę oktavos padėtį nuo oktavos, turinčios vidurį C. Pavyzdžiui, „C, -2“ yra C nata 2 oktavos žemiau vidurio C.

Atkreipkite dėmesį, kad nėra „plokščių“ klavišų. Kiekvieną natą žymi „aštrus“.

Norėdami, kad pianino klaviatūra būtų funkcionali, turime paruošti atvirkštinės paieškos lentelę, kurioje key: valueporas perjungiame taip, kad grojama nata taptų raktu, o raktų kodas - reikšme.

Mums reikia tokios lentelės, nes norime kartoti muzikines natas, kad lengvai sugeneruotume klaviatūrą.

Dabar viskas gali būti sudėtinga: mums iš tikrųjų reikia 2 atvirkštinės paieškos lentelių.

Mes naudojame vieną lentelę, norėdami surasti etiketę, kurią norime parodyti kompiuterio klavišui, kurį paspaudžiame, kad grotume natą (deklaruojama kaip reverseLookupText164 eilutėje), o antrą - ieškoti faktinio paspausto klavišo (deklaruota kaip reverseLookup165 eilutėje).

Gudrus gali suvokti, kad abiejose paieškos lentelėse reikšmės yra raktų kodai, tad koks skirtumas tarp jų?

It turns out that (for reasons unknown to me) when you get a keycode that corresponds to a key and you try to use String.fromCharCode() method on that keycode, you don’t always get back the same string representing the pressed key.

For example, pressing left open bracket yields keycode 219 but when you actually try to convert the keycode back to a string using String.fromCharCode(219) it returns "Û". To get "[", 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 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 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 element. This is where reverseLookupText comes in handy. Inside the same , 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 = '' + s + '' + '

' + n.substr(0,1) + '' + (__octave + parseInt(i)) + '' + (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]));

The first parameter evtListener[0] is a mousedown event declared much earlier on line 7. The second parameter is a function that returns a function. We need reverseLookup to get us the correct keycode and we pass that value as a parameter _temp to the inner function. We will not need reverseLookup to handle actual keydown events.

This code is pre-ES2015 (aka ES6) and the updated, hopefully clearer equivalent is:

const keyCode = reverseLookup[n + ',' + i]; thisKey.addEventListener('mousedown', () => { fnPlayKeyboard({ keyCode }); }); 

After creating and appending all necessary keys to our keyboard, we will need to handle the actual playing of a note.

4. Handle Key Presses

We handle key presses the same way whether the user clicks the key or presses the corresponding computer key through use of the function fnPlayKeyboard on line 260. The only difference is the type of event we use in addEventListener to detect the key press.

We set up an array called keysPressed in line 206 to detect what keys are being pressed/clicked. For simplicity, we will assume that a key being pressed can include it being clicked as well.

We can divide the process of handling key presses into 3 steps: adding the keycode of the pressed key to keysPressed, playing the appropriate note, and removing the keycode from keysPressed.

The first step of adding a keycode is easy:

keysPressed.push(e.keyCode);

where e is the event detected by addEventListener.

If the added keycode is one of the key bindings we assigned, then we call fnPlayNote() on line 304 to play the note associated with that key.

In fnPlayNote(), we first create a new Audio() element container for our note using the generate() method from audiosynth.js. When the audio loads, we can then play the note.

Lines 308-313 are legacy code and seem they can just be replaced by container.play(), though I have not done any extensive testing to see what the difference is.

Removing a key press is also quite straightforward, as you can just remove the key from the keysPressed array with the splice method on line 298. For more details, see the function called fnRemoveKeyBinding().

The only thing we have to watch out for is when the user holds down a key or multiple keys. We have to make sure that the note only plays once while a key is held down (lines 262-267):

var i = keysPressed.length; while(i--) { if(keysPressed[i]==e.keyCode) { return false; } } 

Returning false prevents the rest of fnPlayKeyboard() from executing.

Summary

We have created a fully functioning piano keyboard using vanilla JavaScript!

To recap, here are the steps we took:

  1. We set up our index HTML file to load the appropriate JS files and execute

    playKeyboard() in to generate and make the keyboard functional. We have a element with id= "keyboard" where the keyboard will be displayed on the page.

  2. In our JavaScript file playKeyboard.js, we set up our key bindings with keycodes as keys and musical notes as values. We also create two reverse lookup tables in which one is responsible for looking up the appropriate key label based on the note and the other for looking up the correct keycode.

  3. We dynamically generate the keyboard by looping through every note in each octave range. Each key is created as its own element. We use the reverse lookup tables to generate the key label and correct keycode. Then an event listener on mousedown uses it to call fnPlayKeyboard() to play the note. The

    keydown event calls the same function but does not need a reverse lookup table to get the keycode.

  4. Klavišų paspaudimus, atsirandančius iš pelės paspaudimų arba kompiuterio klavišų paspaudimo, apdorojame 3 žingsniais: prie masyvo pridėkite paspausto rakto kodą, paleiskite atitinkamą natą ir pašalinkite raktinį kodą iš tos masyvo. Turime būti atsargūs, kad pakartotinai nevaidintume užrašo (nuo pat pradžių), kol vartotojas nuolat laikosi nuspaudęs klavišą.

Klaviatūra dabar visiškai veikia, tačiau gali atrodyti šiek tiek nuobodi. Aš paliksiu CSS dalį jums?

Vėlgi, čia yra „JavaScript“ fortepijono klaviatūra, kurią aš padariau nuoroda.

Jei norite sužinoti daugiau apie interneto plėtrą ir patikrinti kitus tvarkingus projektus, apsilankykite mano tinklaraštyje, esančiame 1000 mylių pasaulyje.

Dėkojame už skaitymą ir laimingą kodavimą!