0%

JavaScript Drum Kit 01

01 - JavaScript Drum Kit

一面上班, 一面學習自己從來不會的東西, 真的是一件很辛苦的事情QQ,
從0開始, 從一開始的vscode要怎麼用, 到開始學習html,css, 到現在可以自己刻出畫面那個成就感真的很棒,
連寫function語法都寫得不好 常常會syntax error,

不知道function(e) 是什麼用途,不知道web developer tool 可以怎麼用,
forEach都寫不好, 不知道怎麼讓function可以執行 可以使用IIEF的方式,
這三個月真的過得很充實,
謝謝一路上幫助我的同事, 每天早上的stand up teach, 解決我前一天半夜遇到的問題,
幫我review提出更好的方法, 或是一些建議, 雖然對他們來說只是舉手之勞,
但耽誤大家的時間真的是一件很不好意思的事情,
中間第一次rebase, 多學了一些command checkout ., commit --amand, aws 怎麼用, kill procses, tail -f,
雖然都是一些簡單的東西, 但當你嘗試去了解學習, 這些一開始覺得像天書的東西, 最後你也會成為別人眼中的大神, 不斷努力吧!!!

1
2
試著讓團隊更好, 分享給不懂的人, 教學是一件很快樂事呢.
第一次寫心得, 記錄自己都做了些什麼, 原來是一件令人開心的事情 而不枯燥, 像極了愛情.

鼓勵所有看到這個github的人, 只要堅持做自己想要做的事情, 慢慢的就會走向你想要的結果,

堅持下去儘管最後想放棄了, 但中間的這些過程, 做往後也會是很好的養分,
至少你沒有畫地自限, 儘管最後失敗了, 也會比一開始沒有設目標的人爬得更高更成功.

每天都會想到kobe bryant 你有看過凌晨4點的洛杉磯嗎 ?
沒有, 但我每天都看到凌晨3:30的台北,隔天還是照常上下班, 照常發揮最大的產出, 照常維持運動習慣,要做最好的人.
這些日子自己真的成長了不少, 雖然離合格還差得遠, 但是心態上.能力上.身為一個人類,都越來越好了.

「我們每個人身上都蘊藏著巨大的潛能,但由於我們沒有進行有效的訓練,巨大的潛能只好沉睡在我們身上」。
我們總是忘了,其實自己可以做得更好、其實自己並沒有全力以赴,每個人身上都有無窮的潛能,只是你不知道罷了。

好像開始有一點不一樣了呢…再加油吧!

步驟

Step1. 新增keydown listener

利用window.addEventListener('keydown', playSound);來監聽鍵盤動作。

Step2. 建立functionplaySound

  1. 利用傳入的e.keyCode來取得對應的audio標籤及該按鍵的div標籤
  2. 判斷傳入的e.keyCode是否有對應的audio標籤,若無則退出
  3. 使對應的div加上playing樣式,產生對應的典及特效
  4. 使對應的audio播放時間為0
  5. 播放對應的音檔

    Step3. 新增transitionend listener

  6. 偵測所有包含className='key'的元件
  7. 當該元件觸發特效並結束時(transitionend),呼叫removeTransition

    Step4. 建立functionremoveTransition

  8. 判斷傳入的propretyName是否為transform,若否則退出
  9. 若為transform,則移除playing樣式

JavaScript語法&備註

element.classList

這個會回傳element的class值(陣列),
範例用到了classList的方法add()remove()

1
2
classList.add('aaa', 'bbb', 'ccc'); //新增多個className
classList.remove('aaa', 'bbb', 'ccc'); //移除多個className

如果已經存在/不存在的className則會被忽略。

還有其他方法如:
toggle()偵測是否存在這個className,存在則刪除/不存在則新增
contains()偵測是否存在這個className, 返回true/false
參閱:MDN-Element.classList

**HTMLmediaElement(audio)**:

HTML的audio標籤,在HTML放置如下標籤指定音源

1
<audio src="sound/a.mp3"></audio>

透過javascript來操作:
element.play():進行播放
element.currentTime:指定播放秒數
範例中使用currentTime是為了達到連發的效果XD

參閱:MDN-HTMLMediaElement

forEach

之前沒在javascript中使用的語法,用法如下:

1
arr.forEach(callback function)

我是用for迴圈來比對做語法理解的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let datas = ['data1', 'data2', 'data3'];
//for迴圈寫法
for (let i = 0; i < datas.length; i++) {
console.log(datas[i]);
}
//forEach寫法
datas.forEach(function(data){
console.log(data);
});
//都會輸出
//data1
//data2
//data3

datas.forEach(console.log);
//如果透過上面直接console.log來看到結果是:
//data1 0 ["data1", "data2", "data3"]
//data2 1 ["data1", "data2", "data3"]
//data3 2 ["data1", "data2", "data3"]
//回傳的分別是value, index, array本身內容。

參閱:MDN-Array.prototype.forEach()

箭頭函式(Arrow Function)

ES6的新語法

1
2
3
4
5
6
//傳統寫法
let func1 = function(arg) { console.log('Hi, ' + arg); };
//箭頭函式寫法
let func2 = arg => console.log('Hi, ' + arg);
//補充:如果該function沒有參數要傳,要帶空括號如下
let func3 = () => console.log('Hi');

參閱:MDN-Arrow functions

addEventListener

因為我是是第一次看到transtionend這個event,
所以去MDN查了HTML DOM event記錄連結在此

參閱:MDN-Event reference

template literals

模板文字,同樣屬於第一次看到的東西,
利用` - 反引號(back-tick)或稱重音符(grave accent)來組合字串,
在範圍內可利用${}加上變數操作

例如原本的字串+變數組合寫法:

1
2
3
let str = '<div data-key="' + key + '">' +
'<button>click me</button>' +
'</div>';

改用template string來做只要

1
2
3
let str = `<div data-key="${key}">
<button>click me</button>
</div>`;

`包住字串,利用${}來包變數
這樣可以很輕鬆的組出易於閱讀的組合字串!
不用像以前還要注意單雙引號與+的配合了~

參閱:MDN-Template literals

Array.from

範例中有這段

1
const keys = Array.from(document.querySelectorAll('.key'));

查詢了Array.from才知道這是一個將一個物件或是字串轉為陣列格式的語法,
但當時覺得為何要把陣列在轉成陣列?querySelectorAll不就是返回陣列嗎?
在查下去才發現querySelectorAll返回的是nodeList且nodeList跟Array是不同的!
雖然都很像陣列,但nodeList並沒有array.prototype上的方法!
最簡單的例子是用array.push()去測試,會發現由querySelectAll得到的物件無法用.push()。

1
2
3
4
5
let testNodeList = document.querySelectAll('.key');
testNodeList.push('add'); // <--非陣列會報錯TypeError: testNodeList.push is not a function

let testArray = Array.from(testNodeList);
testArray.push('add'); // <-- 轉為陣列就可以了

至於在範例中轉型的原因,
我想應該是因為若無轉型為Array使用nodeList來forEach可能會導致某些瀏覽器版本錯誤。

nodeList由querySelectorAll及childNodes返回的
參閱:MDN-NodeList

CSS語法&備註

display:flex

CSS3的排版語法,以範例中的來做備註紀錄

1
2
3
4
5
6
7
.keys {
display: flex; /*要使用flex要在元素內先宣告flex*/
flex: 1; /*這是一個簡寫,全部為flex: flex-grow|flex-shrink|flex-basis*/
min-height: 100vh; /*vh代表view height, 百分比呈現*/
align-items: center; /*宣告為flex後才有效的屬性,垂直置中*/
justify-content: center;/*宣告為flex後才有效的屬性,水平置中*/
}

參閱:MDN-flex

探索

原範例只能由鍵盤觸發,
我的探索是為這個範例加上可由滑鼠點擊觸發的功能

const keys = Array.from(document.querySelectorAll('.key'));

//新增click功能綁定至每個class="key"
keys.forEach(key => key.addEventListener('click', playSound));

function playSound(e) {
    //依據不同的事件來取得對應的key_code(e.type可以看,以下是簡寫版)
    let keyCode = e.keyCode || this.getAttribute('data-key');

    const audio = document.querySelector(`audio[data-key="${keyCode}"]`);
    const key = document.querySelector(`div[data-key="${keyCode}"]`);

    if (!audio) return;

    key.classList.add('playing');
    audio.currentTime = 0;
    audio.play();
}

[[DEMO]](https://bobchochola.github.io/javascript30/01_Java-Script-Drum-Kit/index-BobChochola.html)