---
# System prepended metadata

title: '[JS30] Day1. Drum Kit'
tags: [JS30]

---

# [JS30] Day1. Drum Kit
###### tags: `JS30`
## 任務 Task
點擊音效按鈕發出相對應音效，並且按鈕樣式同時改變。

==完成時間：４hr==

## 步驟 Step
1. 使用 `addEventLisener` 監聽 `keydown` 事件
2. 抓取 HTML 的 `data-key` 並放出對應的 `audio`
3. 加入 `class = "playing"` 讓按鈕改變樣式
4. 監聽 `transitionend` 結束時移除 `playing` 標籤

## 筆記 Note
### HTML audio attributes

- src：URL位置
- autoplay：是否自動撥放 boolean / 預設為 false
- loop：是否循環 boolean / 預設為 false
- muted：是否靜音 boolean / 預設為 false
- controls：是否出現控制面板（播放進度、暫停紐、靜音紐）boolean / 預設為 false

==audio JS method==

- play()：播放
- pause()：暫停

==audio JS property==

- currentTime：以秒為單位的音訊位置

DOM：[http://www.w3bai.com/zh-TW/tags/ref_av_dom.html](http://www.w3bai.com/zh-TW/tags/ref_av_dom.html)

### HTML Tag `<kbd>`

```html=
<kbd>Ctrl</kbd>
```

- 鍵盤元素標籤

### HTML `attribute data-*`

```html=
<div data-myid="1234" class = "id"></div>
```

- 自訂data屬性，JS可使用 .dataset 作使用

```javascript=
let myid = document.querySelector(".id").dataset.myid;
```
- 可使用`[data-*]`去選取整個div
```javascript=
let myid = document.querySelector(`div[data-myid="1234"]`);
```

### JS addEventListener(”transitionend”, function())

- transitionend 在 CSS 改變後觸發，可讀取改變的 CSS 的樣式

---

## 遇到問題 Problem
:::danger
⚠️ <font color=black>Problem</font>
:::


原本按下後新增 `class = "playing"` 去改變按鈕外框顏色，而消失的方式為偵測到 `transitionend = transform` 時（CSS樣式更改的最後一項）就將 class 移除。

但如果按的夠快（快於 CSS 設定的時間）或是長按不停，transitionend 一直偵測不到 transform，class 就無法 移除。
:::info
:ok_hand: <font color=black>Revise</font>
:::

改成偵測 `keyup` ，當按鍵放開時，就將 class 移除。
## 想法 Idea
:::warning
:bulb: <font color=black>新增用滑鼠按也能發出聲音</font>
:::

### 方法 method
偵測滑鼠按下去 `mousedown` 然後用 for 迴圈 Nodelist 去偵測每一個按下去的 `data-key` 再將 `data-key` 傳給對應的 `audio` 放出聲音。`class.remove()` 用 `mouseup`

```javascript=
let key = document.querySelectorAll(".key")
  for(let i = 0; i < 9; i++){
    key[i].addEventListener("mousedown",(e) => {
      let keycode = key[i].dataset.key; 
      //找到按下去的 data-key
      let audio = document.querySelector(`audio[data-key="${keycode}"]`); 
      //data-key數字對應audio
      audio.currentTime = 0;
      audio.play();
      key[i].classList.add("playing");
  })
    key[i].addEventListener("mouseup",(e) => {
      key[i].classList.remove("playing");
    })
  }
```
### 🔮 Annie method
`for…of…` 可直接選取 Object 的 Variable（太神奇了傑克！）

</aside>

```javascript=
let buttons = document.querySelectorAll(".key")
  for(let button of buttons){
    button.addEventListener("mousedown",(e) => {
      let audio = document.querySelector(`audio[data-key="${button.dataset.key}"]`);
      audio.currentTime = 0;
      audio.play();
      button.classList.add("playing");
    })
    button.addEventListener("mouseup",(e) => {
      button.classList.remove("playing");
    })
  }
```
## 連結
* [免費 Svg 圖片](https://freesvg.org/)
* [免費音檔](https://freesound.org/)
