JavaScript Drum Kit 指南(純 JS 模擬敲鼓效果)
核心代碼:
<script>
function removeTransition(event) {
if (event.propertyName !== 'transform') return; // 過(guò)濾其中一種事件
event.target.classList.remove('playing'); // 移除高亮的樣式
}
function playSound(event) {
const audio = document.querySelector(`audio[data-key="${event.keyCode}"]`); // 根據(jù)觸發(fā)按鍵的鍵碼,獲取對(duì)應(yīng)音頻
const key = document.querySelector(`div[data-key="${event.keyCode}"]`); // 獲取頁(yè)面對(duì)應(yīng)按鈕 DIV 元素
if (!audio) return; // 處理無(wú)效的按鍵事件
key.classList.add('playing'); // 改變樣式
audio.currentTime = 0; // 每次播放之后都使音頻播放進(jìn)度歸零
audio.play(); // 播放相應(yīng)音效
}
const keys = Array.from(document.querySelectorAll('.key')); // 獲取頁(yè)面所有按鈕元素
keys.forEach(key => key.addEventListener('transitionend', removeTransition)); // 添加 transition 事件監(jiān)聽(tīng)
window.addEventListener('keydown', playSound);
</script>
中文版本完整代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS Drum Kit</title>
<link rel="stylesheet" href="style.css" rel="external nofollow" rel="external nofollow" >
</head>
<body>
<div class="keys">
<div data-key="65" class="key">
<kbd>A</kbd>
<span class="sound">clap</span>
</div>
<div data-key="83" class="key">
<kbd>S</kbd>
<span class="sound">hihat</span>
</div>
<div data-key="68" class="key">
<kbd>D</kbd>
<span class="sound">kick</span>
</div>
<div data-key="70" class="key">
<kbd>F</kbd>
<span class="sound">openhat</span>
</div>
<div data-key="71" class="key">
<kbd>G</kbd>
<span class="sound">boom</span>
</div>
<div data-key="72" class="key">
<kbd>H</kbd>
<span class="sound">ride</span>
</div>
<div data-key="74" class="key">
<kbd>J</kbd>
<span class="sound">snare</span>
</div>
<div data-key="75" class="key">
<kbd>K</kbd>
<span class="sound">tom</span>
</div>
<div data-key="76" class="key">
<kbd>L</kbd>
<span class="sound">tink</span>
</div>
</div>
<audio data-key="65" src="sounds/clap.wav"></audio>
<audio data-key="83" src="sounds/hihat.wav"></audio>
<audio data-key="68" src="sounds/kick.wav"></audio>
<audio data-key="70" src="sounds/openhat.wav"></audio>
<audio data-key="71" src="sounds/boom.wav"></audio>
<audio data-key="72" src="sounds/ride.wav"></audio>
<audio data-key="74" src="sounds/snare.wav"></audio>
<audio data-key="75" src="sounds/tom.wav"></audio>
<audio data-key="76" src="sounds/tink.wav"></audio>
<script>
function removeTransition(event) {
if (event.propertyName !== 'transform') return; // 過(guò)濾其中一種事件
event.target.classList.remove('playing'); // 移除高亮的樣式
}
function playSound(event) {
const audio = document.querySelector(`audio[data-key="${event.keyCode}"]`); // 根據(jù)觸發(fā)按鍵的鍵碼,獲取對(duì)應(yīng)音頻
const key = document.querySelector(`div[data-key="${event.keyCode}"]`); // 獲取頁(yè)面對(duì)應(yīng)按鈕 DIV 元素
if (!audio) return; // 處理無(wú)效的按鍵事件
key.classList.add('playing'); // 改變樣式
audio.currentTime = 0; // 每次播放之后都使音頻播放進(jìn)度歸零
audio.play(); // 播放相應(yīng)音效
}
const keys = Array.from(document.querySelectorAll('.key')); // 獲取頁(yè)面所有按鈕元素
keys.forEach(key => key.addEventListener('transitionend', removeTransition)); // 添加 transition 事件監(jiān)聽(tīng)
window.addEventListener('keydown', playSound);
</script>
</body>
</html>
英文版本完整代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS Drum Kit</title>
<link rel="stylesheet" href="style.css" rel="external nofollow" rel="external nofollow" >
</head>
<body>
<div class="keys">
<div data-key="65" class="key">
<kbd>A</kbd>
<span class="sound">clap</span>
</div>
<div data-key="83" class="key">
<kbd>S</kbd>
<span class="sound">hihat</span>
</div>
<div data-key="68" class="key">
<kbd>D</kbd>
<span class="sound">kick</span>
</div>
<div data-key="70" class="key">
<kbd>F</kbd>
<span class="sound">openhat</span>
</div>
<div data-key="71" class="key">
<kbd>G</kbd>
<span class="sound">boom</span>
</div>
<div data-key="72" class="key">
<kbd>H</kbd>
<span class="sound">ride</span>
</div>
<div data-key="74" class="key">
<kbd>J</kbd>
<span class="sound">snare</span>
</div>
<div data-key="75" class="key">
<kbd>K</kbd>
<span class="sound">tom</span>
</div>
<div data-key="76" class="key">
<kbd>L</kbd>
<span class="sound">tink</span>
</div>
</div>
<audio data-key="65" src="sounds/clap.wav"></audio>
<audio data-key="83" src="sounds/hihat.wav"></audio>
<audio data-key="68" src="sounds/kick.wav"></audio>
<audio data-key="70" src="sounds/openhat.wav"></audio>
<audio data-key="71" src="sounds/boom.wav"></audio>
<audio data-key="72" src="sounds/ride.wav"></audio>
<audio data-key="74" src="sounds/snare.wav"></audio>
<audio data-key="75" src="sounds/tom.wav"></audio>
<audio data-key="76" src="sounds/tink.wav"></audio>
<script>
/** GOAL: When a user opens this page and presses a key that corresponds with
* one of our div elements, we should play the audio clip associated with
* the keypress, add a class to the specific element that matches with the keypress,
* and then remove that class in order to reset the element to it's original state.
*/
(()=> {
const playSound = (e) => {
const soundclip = document.querySelector(`audio[data-key="${e.keyCode}"]`);
const keyelement = document.querySelector(`.key[data-key="${e.keyCode}"]`);
if (!soundclip) return undefined; // Stop function from running if key pressed doesn't match up with our elements
keyelement.classList.add('playing');
// Ensures that the sound clip always plays from the beginning. Otherwise,
// if the 'a' key is pressed twice rapidly, the soundclip will only play through
// once.
soundclip.currentTime = 0;
soundclip.play(); // Play sound
}
const removeTransition = (e) => {
// skip if it's not a transform event
if (e.propertyName !== 'transform') return undefined;
e.target.classList.remove('playing');
}
// Find all elements in the document with a class 'key'
const keys = document.querySelectorAll('.key');
// Listen for any `keydown` events that occur on this browser window instance (this page)
// When a `keydown` event is observered, trigger the `playSound` function, passing in the
// `keydown` event as the argument (e)
window.addEventListener('keydown', playSound);
keys.forEach(key =>
key.addEventListener(
'transitionend',
(e) => removeTransition.call(key, e)
));
})();
</script>
</body>
</html>
在線演示地址:http://demo.jb51.net/js/2017/JavaScript30/JavaScriptDrumKit/index-FINISHED.html
請(qǐng)?jiān)赾hrome瀏覽器下查看效果。
相關(guān)文章
JavaScript實(shí)現(xiàn)瀏覽器網(wǎng)頁(yè)自動(dòng)滾動(dòng)并點(diǎn)擊的示例代碼
這篇文章主要介紹了JavaScript實(shí)現(xiàn)瀏覽器網(wǎng)頁(yè)的自動(dòng)滾動(dòng)并點(diǎn)擊的示例代碼,幫助大家更好的理解和學(xué)習(xí)JavaScript的使用,感興趣的朋友可以了解下2020-12-12
JAVASCRIPT模式窗口中下載文件無(wú)法接收iframe的流
模式窗口中下載文件,有時(shí)在下載時(shí)發(fā)現(xiàn)服務(wù)器無(wú)法接收iframe的流,因?yàn)樵谀J酱翱谥袥](méi)有觸發(fā)iframe的src重新定向事件2013-10-10
JavaScript 通過(guò)Ajax 動(dòng)態(tài)加載CheckBox復(fù)選框
本文通過(guò)實(shí)例代碼給大家介紹了JavaScript 通過(guò)Ajax 動(dòng)態(tài)加載CheckBox復(fù)選框的方法,需要的朋友參考下吧2017-08-08
用director.js實(shí)現(xiàn)前端路由使用實(shí)例
本篇文章主要介紹了director.js實(shí)現(xiàn)前端路由,在不刷新的情況下,利用“#”號(hào)組織不同的URL路徑,并根據(jù)不同的URL路徑進(jìn)行不同的方法調(diào)用。有興趣的了解一下。2017-01-01
xmlplus組件設(shè)計(jì)系列之下拉刷新(PullRefresh)(6)
xmlplus 是一個(gè)JavaScript框架,用于快速開(kāi)發(fā)前后端項(xiàng)目。這篇文章主要介紹了xmlplus組件設(shè)計(jì)系列之下拉刷新,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
淺析Javascript ES6新增值比較函數(shù)Object.is
在Javascript中判斷相等是很常見(jiàn)的,常用的判斷有“==”,“===”,“!=”,“!==”,今天這篇文章我們來(lái)學(xué)習(xí)ES6中的一個(gè)方法Object.is(),有需要的可以參考學(xué)習(xí)。2016-08-08

