挑戰 JS30 #1 - JavaScript Drum Kit

更新於 發佈於 閱讀時間約 7 分鐘

這系列文章會記錄 JS30 當次挑戰時使用到的語法和相關知識。

JS30 官方有提供所有製作網頁的資源,不需要任何事前準備,就能無痛開始撰寫 JS,寫完之後還有 JS30 作者提供的解答,不知道怎麼下手時可以參考、寫完之後也能了解更多解法,改善自己的寫法。

本次的挑戰是「JavaScript Drum Kit」,需要達成的目標是:

「使用者按下鍵盤特定按鍵,按鍵會發光、同時播放相對應的音效。」

根據上面這個目標,大略知道該挑戰牽涉到以下面向:

  • 事件綁定、鍵盤事件
  • 流程控制
  • 操作音效物件
  • DOM 操作 - 包括樣式修改、取得 DOM 元素等

嘗試拆解流程

流程圖

流程圖

這個挑戰有個小細節,就是每次按下鍵盤後,都必須將音效時間軸歸零,這樣在每次觸發時才會從頭開始播放音效。

知識點

音效物件

網頁中引入音效可以使用 <audio> 元素,原來 audio 本身有 API 可以進行操作,相當方便,以下就來了解看看吧。

<audio> 標籤

<audio​ src="filePath"></audio>

常見屬性

  • autoplay:自動播放音檔
  • controls:出現控制條
  • loop:循環播放

有看到一些文章會建議搭配 source 標籤,避免某些音檔格式瀏覽器不支援,而發生預期外的效果。如果 source 的第一個格式不支援,就會向下讀取其他項目,通常 mp3 會是最普及的格式,可以放在最後。

<audio autoplay>
<source src="xxx.ogg">
<source src="xxx.mp3">
你的瀏覽器不支援 HTML5 音訊格式。
</audio>

audio 相關 API

const audio = document.querySelector("audio")

//開始播放​
audio.play();

//暫停播放​
audio.pause();

//將音檔秒數歸零​
//audio 物件還有許多屬性,幾乎完全可以透過 JS 控制 audio
audio.currentTime = 0;

<kbd> 標籤

語意標籤,表示「鍵盤輸入按鍵」,預設樣式就會將字型變為等寬字(monospace)

附上此次實作結果

更好的寫法

參考作者的寫法,發現在取得 DOM 元素時就先篩選出符合的元素,但筆者在這邊都使用 forEach 迴圈做篩選。

下方比較兩者寫法,可以看出筆者寫法較為冗長,可讀性較低,且跑迴圈會佔較多效能。

  • 筆者的寫法
const keys = document.querySelectorAll(".key");

const filter = function (list, userKeyboard) {
let el;
list.forEach((item) => {
if (item.dataset.key === userKeyboard) {
el = item;
}
});
return el;
};

const playAudio = function (e) {
const audios = document.querySelectorAll("audio");
const userKeyboard = String(e.keyCode);
if (filter(keys, userKeyboard)) {
filter(keys, userKeyboard).classList.add("playing");
filter(audios, userKeyboard).currentTime = 0;
filter(audios, userKeyboard).play();
}
};
  • 作者的寫法
function playSound(e) {
const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
const key = document.querySelector(`div[data-key="${e.keyCode}"]`);
console.log(e.keyCode);
if (!audio) return;

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


增進使用體驗

製作完成後,發現有以下幾點可以做調整:

  1. 目前重複按下同一個鍵盤按鍵時,網頁按鈕樣式不會重複觸發,會一直亮著,雖然不影響使用,但希望有更細緻的體驗
  2. 如果完成第 1 點,會發現若鍵盤事件使用 keydown,當使用者按著按鍵不放時,事件會連續觸發,到某個程度時按鈕樣式就不再變動(簡言之「看起來」就像壞掉了XD);若鍵盤事件使用 keyup,雖然解決了事件重複觸發的問題,但筆者認為使用起來不符合預期效果,一般使用者應該會預期按下去的瞬間就發出音效,變成放開按鍵才發出音效似乎不夠即時

實作

一、重複點擊按鈕時,每次都會改變按鈕樣式

這部分是參考作者提供的解法,是使用transitionend 事件,監聽帶有 transition 屬性的元素,當 transitioned 結束時會觸發事件,有兩個情況下無法觸發該事件:

  • 在 transition 觸發以前元素就被設定 display: none
  • 有修改目標節點的 transition-property 屬性
function removeTransition(e) {
console.log(e.propertyName);
if (e.propertyName !== "transform") return;
e.target.classList.remove("playing");
}

作者是透過 propertyName 找到 transform 屬性,但似乎會導致重複觸發時按鈕樣式就不會再變動,不確定原因為何,目前想到的解決方式可往下看第二點。

二、在使用 keydown 的情況下,可以連續觸發樣式,且保持運作正常

解法1: 直接在 keyup 事件上綁定「清除按鈕樣式」的處理器,有點像買保險的感覺XD

let keys = document.querySelectorAll(".key");
const removeSound = function (e) {
keys.forEach((item) => {
item.classList.remove("playing");
});
};
window.addEventListener("keyup", removeSound);

解法2: transitionend 事件的 propertyName,找到除了 transform 以外的其他屬性,就能正常運作,這部分原因尚待釐清。

目前想到的解法是這樣,如果有更好的再補上。

題外話

發現下載後的檔案都有 favicon(瀏覽器頁籤會顯示的 icon),意外發現這個網站,可以自行替換掉後面的表情符號,蠻有趣的XD

今天就介紹到這裡,若有錯誤歡迎指正,也歡迎大家分享自己的看法。

參考資料

留言
avatar-img
留言分享你的想法!
avatar-img
傑米的沙龍
7會員
30內容數
正在一點一滴學習程式,相信知識量總有一天會匯聚成大海,目前專門研究前端中。
你可能也想看
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
孩子寫功課時瞇眼?小心近視!這款喜光全光譜TIONE⁺光健康智慧檯燈,獲眼科院長推薦,網路好評不斷!全光譜LED、180cm大照明範圍、5段亮度及色溫調整、350度萬向旋轉,讓孩子學習更舒適、保護眼睛!
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
創作者營運專員/經理(Operations Specialist/Manager)將負責對平台成長及收入至關重要的 Partnership 夥伴創作者開發及營運。你將發揮對知識與內容變現、影響力變現的精準判斷力,找到你心中的潛力新星或有聲量的中大型創作者加入 vocus。
Thumbnail
學習混音可以分為幾個步驟,即使你沒有經驗,也能逐步掌握這門技術
Thumbnail
學習混音可以分為幾個步驟,即使你沒有經驗,也能逐步掌握這門技術
Thumbnail
這篇文章是來響應跳鼠飛行日記的30天歌單挑戰 Day1-Day5,搜集了以金屬樂為主,我常聽的工作與創作用音樂。 其實我聽的金屬樂非常偏科,大量集中在主唱是女性的樂團上,不過為了顧及推薦的多樣性,還是會將我常聽且知名度高的樂團包含在名單內。 這個小系列會包括三十首歌,每篇十首,那就開始吧!
Thumbnail
這篇文章是來響應跳鼠飛行日記的30天歌單挑戰 Day1-Day5,搜集了以金屬樂為主,我常聽的工作與創作用音樂。 其實我聽的金屬樂非常偏科,大量集中在主唱是女性的樂團上,不過為了顧及推薦的多樣性,還是會將我常聽且知名度高的樂團包含在名單內。 這個小系列會包括三十首歌,每篇十首,那就開始吧!
Thumbnail
我是一個超級愛聽音樂的孩子。 音樂幾乎是我療癒、平靜心情的一個方式,以一個藝術創意型人來說,只要一個人的空間就會播放音樂,而音樂類型偏日韓流行類,在冥想、靜心、睡覺才會使用心靈音樂。 所以為什麼要試隨機模式? 我在最近深深感受到,隨機播放模式,也是種另類的「宇宙建議或者提醒」。
Thumbnail
我是一個超級愛聽音樂的孩子。 音樂幾乎是我療癒、平靜心情的一個方式,以一個藝術創意型人來說,只要一個人的空間就會播放音樂,而音樂類型偏日韓流行類,在冥想、靜心、睡覺才會使用心靈音樂。 所以為什麼要試隨機模式? 我在最近深深感受到,隨機播放模式,也是種另類的「宇宙建議或者提醒」。
Thumbnail
最近在練習吉他的彈奏,靈機一動,對著電視就練了起來。 原來我把電視轉到YouTube,找一些曾經聽過的懷舊老歌,先找到它的單音,再找它的調門和弦,最後就跟著一起彈奏起來,時不時還跟著唱。 這其實是我心目中最理想的「卡拉OK」,號稱「純人工手動的吉他卡拉OK」,因為這樣的音樂境界在我心目中才算OK
Thumbnail
最近在練習吉他的彈奏,靈機一動,對著電視就練了起來。 原來我把電視轉到YouTube,找一些曾經聽過的懷舊老歌,先找到它的單音,再找它的調門和弦,最後就跟著一起彈奏起來,時不時還跟著唱。 這其實是我心目中最理想的「卡拉OK」,號稱「純人工手動的吉他卡拉OK」,因為這樣的音樂境界在我心目中才算OK
Thumbnail
大約是在十多年以前,在公共電視台看了一個節目,裡面出現了一個音樂指揮家。在節目影片中有一段,是這名指揮家在翻閱一本厚厚的交響樂譜,隨後出現了他自己的旁白,大意是說當他看著樂譜的時候,他的腦海中會自動地出現各種樂器的聲音——它們依照樂譜裡的順序自動出現,開始交互起落、有強有弱,最後
Thumbnail
大約是在十多年以前,在公共電視台看了一個節目,裡面出現了一個音樂指揮家。在節目影片中有一段,是這名指揮家在翻閱一本厚厚的交響樂譜,隨後出現了他自己的旁白,大意是說當他看著樂譜的時候,他的腦海中會自動地出現各種樂器的聲音——它們依照樂譜裡的順序自動出現,開始交互起落、有強有弱,最後
Thumbnail
本文分享了作者初學樂器時的試煉,如何突破與學習樂器時遇到的困難。作者講述了從音樂基礎學習的重要性,並提到了一個Youtuber的節奏練習影片推薦。
Thumbnail
本文分享了作者初學樂器時的試煉,如何突破與學習樂器時遇到的困難。作者講述了從音樂基礎學習的重要性,並提到了一個Youtuber的節奏練習影片推薦。
Thumbnail
這系列文章會記錄 JS 30 當次挑戰時使用到的語法和相關知識。JS 30 官方有提供所有製作網頁的資源,不需要任何事前準備,就能無痛開始撰寫 JS,寫完之後還有 JS 30 作者提供的解答,不知道怎麼下手時可以參考、寫完之後也能了解更多解法,改善自己的寫法。
Thumbnail
這系列文章會記錄 JS 30 當次挑戰時使用到的語法和相關知識。JS 30 官方有提供所有製作網頁的資源,不需要任何事前準備,就能無痛開始撰寫 JS,寫完之後還有 JS 30 作者提供的解答,不知道怎麼下手時可以參考、寫完之後也能了解更多解法,改善自己的寫法。
Thumbnail
不會畫畫,不會作曲,只要出張嘴,就能當魔法師,還是自帶畫畫與音樂屬性的魔法師。
Thumbnail
不會畫畫,不會作曲,只要出張嘴,就能當魔法師,還是自帶畫畫與音樂屬性的魔法師。
Thumbnail
在可以指定音效,在顯示氣泡圖標時自動播放音效。
Thumbnail
在可以指定音效,在顯示氣泡圖標時自動播放音效。
Thumbnail
今天要來介紹一款我在教學以及自己在練習時常使用的App-Soundcorset調音器。 由於這款App可同時開節拍器來調音,可移調練習與音叉音感練習,再加上乾淨易操作的介面,已經超過500萬人次下載。
Thumbnail
今天要來介紹一款我在教學以及自己在練習時常使用的App-Soundcorset調音器。 由於這款App可同時開節拍器來調音,可移調練習與音叉音感練習,再加上乾淨易操作的介面,已經超過500萬人次下載。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News