iT邦幫忙

2022 iThome 鐵人賽

DAY 1
0

JavaScript30 介紹

JS30 為加拿大的 Wes Bos 工程師所建立的免費課程,課程會在三十天的時間帶領學生以原生的 HTML + CSS + JavaScript 語法,解決課堂上的 30 個前端開發小專案,以此來逐步建立對於前端語法的基本知識。

前言

由於我英文稍差的關係 QwQ,本文將以 Alex 宅幹嘛 的 JS30 中文導讀為主要的學習方式,另外會採用 Web Bos 每堂課提供給我們的 初始文件,裡面有已經寫好基本 HTML + CSS 的檔案,只要再依照專案的要求加上進階的 CSS 和 JS 效果即可。

本文會盡量以文字的方式,紀錄這 30 天每一個專案的實作,希望在這 30 天的時間能讓自己更加的認識 JavaScript


01 - JavaScript Drum Kit

專案簡介

第一天的目標是建置一個網頁上的架子鼓,隨著使用者按下鍵盤的按鍵,會發出各種不同音色的鼓、鈸聲,並在畫面上顯示按鍵的打擊特效(彈跳、發光)

課程影片:JS30 01
導讀影片:Alex

初始文件

Github 檔案位置:01 - JavaScript Drum Kit

網頁一開始的樣子如下,這時候網頁沒有任何的互動效果和動畫
一開始ㄉ樣子

可以先去看看 最後的成品

正式製作

流程

將程式的要求拆分步驟後,我們需要做的事情如下

  1. 偵測鍵盤按鍵被按下
  2. 播放音樂
  3. 呈現按下按鍵的特效
  4. 讓按鍵回歸原始樣式

偵測鍵盤按鍵被按下

在這裡我們會使用 window.addEventListener('事件', '觸發事件後執行的函式') 監聽行為

在鍵盤按鍵被按下後會觸發 keydown 事件,鬆開後會觸發 keyup 事件,在此希望可以在案下時就觸發,所以選擇使用 keydown 事件做偵測

第一步驟的 JS 程式如下

function playSound(){
    console.log('按鍵事件監聽成功')
}

window.addEventListener('keydown', playSound);

播放音樂

在這裡我們會利用 const audio = document.querySelector('元素') 選取在 HTML 已有的 Audio 元素音檔,再以 audio.play() 播放音訊

選取音檔 -> KeyboardEvent & KeyCode

在這時候我們可以在 playSound() 中加入 console.log(),我們會在網頁的 Console 看到 KeyboardEvent,展開後會有密密麻麻的東西

function playSound(e){
    console.log(e)
}

備註:也可以利用 這個網站 看 KeyboardEvent 的資訊


我們跳過大部分的無用資訊,下面有一個名為 keyCode的數值,我們可以利用這個數值和 data-* 屬性結合應用,選取不同的音檔

function playSound(e){
  console.log(e); 
  const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
}

備註:括號裡的應用是 ES6 樣板字面值 -> ` ` 語法

撥放音樂

我們可以利用 audio.play(); 函式撥放音檔,另外要注意的細節是,如果使用者按下的 KeyCode 是不存在的元素和音檔,要即時 return 中止掉

function playSound(e){
  //console.log(e); 
  const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
  if(!audio) return;
  audio.play(); 
}

現在在按下按鍵後已經可以撥放音訊了,但美中不足的是無法做到音訊的連續撥放(連擊鼓聲),原因是在音訊撥放完之前,audio.play() 是不會有作用的。

因此我們可以加上 audio.currentTime = 0 初始化音檔,達成連續撥放

function playSound(e){
  //console.log(e); 
  const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
  if(!audio) return;
  
  audio.currentTime = 0;
  audio.play(); 
}

呈現按下按鍵的特效

在這裡我們一樣會利用 const key = document.querySelector('元素') ,搭配 KeyCode 選取在 HTML 已有的 div 元素,再以 key.classList.add('playing') 的方式,加上原始文件有的 CSS 屬性特效

function playSound(e){
  //console.log(e); 
  const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
  const key = document.querySelector(`div[data-key="${e.keyCode}"]`);
  if(!audio) return;
  
  audio.currentTime = 0;
  audio.play(); 
  
  key.classList.add('playing');
}

到這裡的效果圖如下

讓按鍵回歸原始樣式

我們最後的成品希望能藉由快速的加上和移除特效,模擬敲擊的過程

要移除按鍵的 .playing 可以利用 key.addEventListener() 監聽 'transitionend' 事件,鎖定移除目標,再藉由 e.currentTarget.classList.remove('playing') 移除

我們在這裡利用 key.forEach({}) 的方式幫所有按鍵加上監聽

key.forEach(key => { // 與 for 迴圈類似,可以遍歷 key 物件中的元素
  key.addEventListener('transitionend', removeTranstion);
})

一樣,先看看他給我們的資訊,由此可以知道每個 CSS 屬性都會有自己獨特的 "transitionend"

function removeTranstion(e){
  console.log(e); 
}

因此我們取 "transform" 為基準,並利用 e.currentTarget.classList.remove('playing') 達成移除目標

function removeTranstion(e){
  // console.log(e); // 由此知道每個屬性都會有自己獨特的 "transitionend"
  if(e.propertyName === 'transform'){ // 取 "transform" 為基準
    e.currentTarget.classList.remove('playing');  // 在對應元素移除名為 "playing" 的 class
  }
}

最後程式碼

<script>

function playSound(e){
  console.log(e); // 由此知道 e 代表的 keyboardEvent 的內容,本次會取 keyCode 做主要利用
  
  const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`); // 依照所按下的按鍵,選取對應的音檔
  // console.log(audio);
  if(audio){
    audio.currentTime = 0; // 初始化音檔,達成連續播放
    audio.play(); 
  } 

  const key = document.querySelector(`div[data-key="${e.keyCode}"]`); // 依照所按下的按鍵,選取與之對應的元素 <div> 
  // console.log(key);
  if(key){
    key.classList.add('playing'); // 在對應的元素添加名為 "playing" 的 class
  } 
}

function removeTranstion(e){
  // console.log(e); // 由此知道每個屬性都會有自己獨特的 "transitionend"
  if(e.propertyName === 'transform'){ // 取 "transform" 為基準
    e.currentTarget.classList.remove('playing');  // 在對應元素移除名為 "playing" 的 class
  }
}

const key = document.querySelectorAll('.key'); // 選取所有包含 class => "key" 的元素  
// console.log(key);

key.forEach(key => { // 與 for 迴圈類似,可以遍歷 key 物件中的元素
  key.addEventListener('transitionend', removeTranstion); // 將所有元素增加 'transitionend' 事件的監聽
})

window.addEventListener('keydown', playSound); // 在網頁增加 'keydown' 事件的監聽
</script>

結語

以上是第一天的製作紀錄,如有錯誤或不足的地方還請多多指教 >.<

JavaScript30
[ Alex 宅幹嘛 ] ?‍? 深入淺出 Javascript30 快速導覽:Day 1:JavaScript Drum Kit
MDN Web Docs - data-*
MDN Web Docs - Template_literals


下一篇
JS30 -> 02 - JS and CSS Clock
系列文
剛接觸前端一個月的小白 - JavaScript30 挑戰筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言