JS30,是由加拿大工程師Wes Bos所建立一系列課程,課程中我們可以學到很多Javascript程式語言的實際應用,例如如何操作Document中的DOM以及資料的API,對於剛踏入Javascript領域的新鮮人來說,是一個非常有趣且扎實的課題。[1]
因為本身也是剛踏入Javascript的新鮮人,希望能利用這次的比賽機會,記錄下自己的學習歷程以及心得。在此新手也能懂的JS30的文章中,將以一天一章的方式完成JS30的訓練,並針對每個章節的內容,闡述內容的思考邏輯以及方法,讓JS新手們能從這系列文章中,學習各種JS中的方法及技巧,對Javascript這個程式語言能有更進一步的認識,並希望能透過自己的經驗與想法,能激發出更多不同的火花!
JS30第一天的內容就是一個非常有趣的例子,透過結合音樂元素,創造出在頁面上打爵士鼓的體驗!
實作連結
在作者提供的範例中,我們可以發現當按下指定的按鈕時,畫面對應的地方會出現特效,且發出對應的聲音。因此可以判斷出當按下對應的按鍵時,總共發生了三件事情:
因自己本身尚未使用過data-attribute
這個屬性,因此在一開始就分別給各個div
元素以及audio
元素加上id,方便後續利用getElementById
來取的元素,內容如下:
<div data-key=65 id="key65" class="key"></div>
<div data-key=83 id="key83" class="key"></div>
<div data-key=68 id="key68" class="key"></div>
<div data-key=70 id="key70" class="key"></div>
<div data-key=71 id="key71" class="key"></div>
<div data-key=72 id="key72" class="key"></div>
<div data-key=74 id="key74" class="key"></div>
<div data-key=75 id="key75" class="key"></div>
<div data-key=76 id="key76" class="key"></div>
<audio data-key=65 id="audio65" src="sounds/clap.wav"></audio>
<audio data-key=83 id="audio83" src="sounds/hihat.wav"></audio>
<audio data-key=68 id="audio68" src="sounds/kick.wav"></audio>
<audio data-key=70 id="audio70" src="sounds/openhat.wav"></audio>
<audio data-key=71 id="audio71" src="sounds/boom.wav"></audio>
<audio data-key=72 id="audio72" src="sounds/ride.wav"></audio>
<audio data-key=74 id="audio74" src="sounds/snare.wav"></audio>
<audio data-key=75 id="audio75" src="sounds/tom.wav"></audio>
<audio data-key=76 id="audio76" src="sounds/tink.wav"></audio>
首先為了在特定條件下觸發功能,我們需要給一個EventListener
來監聽事件的發生,在此我們需要監聽的動作有兩項:
如此一來,我們需要在頁面上監聽keydown(按下按鍵)
以及keyup(放開按鍵)
這兩個事件,而當事件發生時,需分別執行play以及stop這兩個函式:
window.addEventListener('keydown', play);
window.addEventListener('keyup', stop);
從範例當中,我們得知觸發事件的9個按鍵分別為A、S、D、F、G、H、J、K、L,因此當按下的按鍵必須為對應的按鍵才能觸發功能。
透過event.keyCode
這個屬性,可以取得按下按鍵這個事件時,所按下按鍵的編碼。利用按鍵的編碼,我們就能判斷出按鍵是否為觸發動作的按鍵。在下面的參考連結中提供一個網站(keycode)給大家,可以快速知道每個案件對應的Keycode,十分的方便。[2]
此外,筆者在這邊有一個有趣的發現,透過event.keyCode
屬性,我們只能得知目前按下按鍵,但是並無法得知目前輸入的內容。但是如果使用event.key
這個屬性的話,我們就可以得知目前輸入的值,不管是大寫、小寫,甚至連注音都能讀取出來喔!
按下按鍵時,頁面會執行play這個函式,離開按鍵時,則執行stop這個函式。函式中的第一件事,必須判斷按下的的是否為對應的按鍵,是的話才繼續執行後續的動作。
play函式中,在一開始判斷出對應的按鍵之後,先透過document.getElementById
取得我們要動作的元素,再利用element.setAttribute()
的方法,將所取得元素之class,由原本的key修改為playing,藉此來取得playing時的CSS設定。
音效的播放,使用相同方法取得對應的audio元素之後,再利用audio.play()
播放其的音效內容。
而函式stop中,也使用一樣方法,將所取得元素之class,由原本的playing修改回key,並利用class間CSS設定的轉換,來產生按下按鍵時產生特效,離開按鍵時則變環原本的樣子。
音效的停止,也使用相同方法,在取得對應的audio元素之後,利用audio.load()
停止播放其的音效內容。而這邊特別注意到,load()
的功能並不是停止播放,而是重新加載。pause()
的功能才是停止音效的播放。
function play(event) {
//給定一變數來取得按下按鍵的keycode
let keyboard = event.keyCode;
//判斷式:當取得的keycode為符合的9個按鍵才會往下執行
if (keyboard === 65 || keyboard === 83 || keyboard === 68 || keyboard ===70 || keyboard ===71 || keyboard ===72 || keyboard ===74 || keyboard ===75 || keyboard ===76) {
//取的對應的div元素將其改為playing這個class
document.getElementById("key" + keyboard).setAttribute('class', 'playing');
//取的對應的audio元素並播放
document.getElementById("audio" + keyboard).play();
};
};
function stop(event) {
//給定一變數來取得按下按鍵的keycode
var keyboard = event.keyCode;
//判斷式:當取得的keycode為符合的9個按鍵才會往下執行
if (keyboard === 65 || keyboard === 83 || keyboard === 68 || keyboard ===70 || keyboard ===71 || keyboard ===72 || keyboard ===74 || keyboard ===75 || keyboard ===76) {
//取的對應的div元素將其改回key這個class
document.getElementById("key" + keyboard).setAttribute('class', 'key');
//取的對應的audio元素並重新讀取
document.getElementById("audio" + keyboard).load();
};
};
在這邊一開始寫code的時候,在函式stop中並沒有設定audio的動作,因此當按下按鍵的時候,發現到每個音效的時間長短不一,並且放開按鍵時,音效會繼續播放直到結束。後來在函式stop中嘗試加上pause()
以及load()
,發現後者才是我們要的效果。pause()
會將播放暫停,但是當下一次播放時,會從上一次暫停的地方繼續。load()
則是將音樂重新加載,因此當我們再次按下按鍵時,便會從頭開始播放。
這邊也在下方參考資料中,提供w3school網站連結,讓大家了解音樂以及影片的一些操作method以及相關property。[3]
原作者在影片當中,則是使用data attribute
來取得對應的元素,可以不用額外加上id來抓取,並有效減少coding的長度。透過data attribute
,我們可以添加自己需要的屬性名稱。而在此屬性名稱當中,不能包含大寫字體。此外,如果我們需要取出這個值,也有方法可以利用。[4]
//audio 元素取得
document.querySelector(`audio[data-key="${e.keyCode}"]`);
//div 元素取得
document.querySelector(`div[data-key="${e.keyCode}"]`);
//data-* attribute 值取得方法
element.dataset.key
在此課題當中,我們學到以下的技能:
以上是JS30第一篇帶給我的想法,如果各位讀者有些特別的點子以及coding技巧能交流的話,也歡迎留言指教,感謝您的閱讀。