JavaScript Drum Kit 指南(纯 JS 模拟敲鼓效果)


Posted in Javascript onJuly 23, 2017

核心代码:

<script>
 function removeTransition(event) {
  if (event.propertyName !== 'transform') return; // 过滤其中一种事件
  event.target.classList.remove('playing'); // 移除高亮的样式
 }

 function playSound(event) {
  const audio = document.querySelector(`audio[data-key="${event.keyCode}"]`); // 根据触发按键的键码,获取对应音频
  const key = document.querySelector(`div[data-key="${event.keyCode}"]`); // 获取页面对应按钮 DIV 元素
  if (!audio) return; // 处理无效的按键事件

  key.classList.add('playing'); // 改变样式
  audio.currentTime = 0; // 每次播放之后都使音频播放进度归零
  audio.play(); // 播放相应音效
 }

 const keys = Array.from(document.querySelectorAll('.key')); // 获取页面所有按钮元素
 keys.forEach(key => key.addEventListener('transitionend', removeTransition)); // 添加 transition 事件监听
 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; // 过滤其中一种事件
  event.target.classList.remove('playing'); // 移除高亮的样式
 }

 function playSound(event) {
  const audio = document.querySelector(`audio[data-key="${event.keyCode}"]`); // 根据触发按键的键码,获取对应音频
  const key = document.querySelector(`div[data-key="${event.keyCode}"]`); // 获取页面对应按钮 DIV 元素
  if (!audio) return; // 处理无效的按键事件

  key.classList.add('playing'); // 改变样式
  audio.currentTime = 0; // 每次播放之后都使音频播放进度归零
  audio.play(); // 播放相应音效
 }

 const keys = Array.from(document.querySelectorAll('.key')); // 获取页面所有按钮元素
 keys.forEach(key => key.addEventListener('transitionend', removeTransition)); // 添加 transition 事件监听
 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.3water.com/js/2017/JavaScript30/JavaScriptDrumKit/index-FINISHED.html

请在chrome浏览器下查看效果。

Javascript 相关文章推荐
点击广告后才能获得下载地址
Oct 26 Javascript
利用js跨页面保存变量做菜单的方法
Jan 17 Javascript
JavaScript与Div对层定位和移动获得坐标的实现代码
Sep 08 Javascript
浅析JavaScript动画
Jun 10 Javascript
js实现常用排序算法
Aug 09 Javascript
Javascript 实现放大镜效果实例详解
Dec 03 Javascript
Ionic3实现图片瀑布流布局
Aug 09 Javascript
使用Electron构建React+Webpack桌面应用的方法
Dec 15 Javascript
jQuery实现的简单对话框拖动功能示例
Jun 05 jQuery
jQuery实现移动端图片上传预览组件的方法分析
May 01 jQuery
详解如何修改 node_modules 里的文件
May 22 Javascript
JavaScript 绘制饼图的示例
Feb 19 Javascript
JavaScript30 一个月纯 JS 挑战中文指南(英文全集)
Jul 23 #Javascript
jquery实现下拉菜单的手风琴效果
Jul 23 #jQuery
基于Vue.js实现tab滑块效果
Jul 23 #Javascript
JavaScript判断浏览器和hack滚动条的写法
Jul 23 #Javascript
原生js FileReader对象实现图片上传本地预览效果
Mar 27 #Javascript
JavaScript解析任意形式的json树型结构展示
Jul 23 #Javascript
Node.js如何实现注册邮箱激活功能 (常见)
Jul 23 #Javascript
You might like
Zend的Registry机制的使用说明
2013/05/02 PHP
Windows下的PHP安装文件线程安全和非线程安全的区别
2014/04/23 PHP
php中有关字符串的4个函数substr、strrchr、strstr、ereg介绍和使用例子
2014/04/24 PHP
php版微信发红包接口用法示例
2016/09/23 PHP
javascript中的parseInt和parseFloat区别
2013/07/12 Javascript
JavaScript数据结构和算法之二叉树详解
2015/02/11 Javascript
javascript通过获取html标签属性class实现多选项卡的方法
2015/07/27 Javascript
jQuery的ajax中使用FormData实现页面无刷新上传功能
2017/01/16 Javascript
vuejs2.0实现一个简单的分页示例
2017/02/22 Javascript
将input框中输入内容显示在相应的div中【三种方法可选】
2017/05/08 Javascript
微信小程序实战篇之购物车的实现代码示例
2017/11/30 Javascript
学习Vue组件实例
2018/04/28 Javascript
vue实现学生录入系统之添加删除功能
2018/07/11 Javascript
在小程序/mpvue中使用flyio发起网络请求的方法
2018/09/13 Javascript
Vue实现渲染数据后控制滚动条位置(推荐)
2019/12/09 Javascript
python爬取网站数据保存使用的方法
2013/11/20 Python
python求加权平均值的实例(附纯python写法)
2019/08/22 Python
Python下应用opencv 实现人脸检测功能
2019/10/24 Python
pytorch: Parameter 的数据结构实例
2019/12/31 Python
Html5实现首页动态视频背景的示例代码
2019/09/25 HTML / CSS
html5利用canvas实现颜色容差抠图功能
2019/12/23 HTML / CSS
Tommy Hilfiger澳洲官网:美国高端休闲领导品牌
2020/12/16 全球购物
医学护理毕业生自荐信
2013/11/07 职场文书
毕业生应聘幼儿园的自荐信
2013/11/20 职场文书
英语教师岗位职责
2014/03/16 职场文书
《数星星的孩子》教学反思
2014/04/11 职场文书
2014年五一劳动节社区活动总结
2014/04/14 职场文书
小学“向国旗敬礼”网上签名寄语活动总结
2014/09/27 职场文书
领导班子专题民主生活会情况想汇报
2014/09/30 职场文书
2014年标准化工作总结
2014/12/17 职场文书
遗失证明范文
2015/06/19 职场文书
六五普法先进个人主要事迹材料
2015/11/03 职场文书
Python异常类型以及处理方法汇总
2021/06/05 Python
使用javascript解析二维码的三种方式
2021/11/11 Javascript
24年收藏2000多部退役军用电台
2022/02/18 无线电
httpclient调用远程接口的方法
2022/08/14 Java/Android