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 相关文章推荐
InnerHtml和InnerText的区别分析
Mar 13 Javascript
SharePoint 客户端对象模型 (一) ECMA Script
May 22 Javascript
javascript实现跳转菜单的具体方法
Jul 05 Javascript
JS常见问题整理(持续更新)
Aug 06 Javascript
javascript根据像素点取位置示例
Jan 27 Javascript
JavaScript框架是什么?怎样才能叫做框架?
Jul 01 Javascript
js中对函数设置默认参数值的3种方法
Oct 23 Javascript
详解jQuery中的事件
Dec 14 Javascript
bootstrap导航条实现代码
Dec 28 Javascript
touch.js 拖动、缩放、旋转 (鼠标手势)功能代码
Feb 04 Javascript
了解JavaScript表单操作和表单域
May 27 Javascript
JavaScrip数组去重操作实例小结
Jun 20 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
php检测数组长度函数sizeof与count用法
2014/11/17 PHP
smarty模板引擎中自定义函数的方法
2015/01/22 PHP
你的编程语言可以这样做吗?
2006/09/07 Javascript
javascript form 验证函数 弹出对话框形式
2009/06/23 Javascript
Three.js源码阅读笔记(光照部分)
2012/12/27 Javascript
open 动态修改img的onclick事件示例代码
2013/11/13 Javascript
jQuery学习笔记之 Ajax操作篇(一) - 数据加载
2014/06/23 Javascript
jQuery使用height()获取高度需要注意的地方
2014/12/13 Javascript
详解AngularJS中的表达式使用
2015/06/16 Javascript
你有必要知道的25个JavaScript面试题
2015/12/29 Javascript
基于Bootstrap和jQuery构建前端分页工具实例代码
2016/11/23 Javascript
深入理解JavaScript 参数按值传递
2017/05/24 Javascript
js canvas实现简单的图像扩散效果
2020/06/28 Javascript
JavaScript实现为事件句柄绑定监听函数的方法分析
2017/11/14 Javascript
JS运动特效之链式运动分析
2018/01/24 Javascript
使用vux实现上拉刷新功能遇到的坑
2018/02/08 Javascript
jQuery - AJAX load() 实例用法详解
2019/08/27 jQuery
基于redis的小程序登录实现方法流程分析
2020/05/25 Javascript
JavaScript中的执行环境和作用域链
2020/09/04 Javascript
python中ConfigParse模块的用法
2014/09/29 Python
解决Pycharm 包已经下载,但是运行代码提示找不到模块的问题
2019/08/31 Python
PyCharm专业最新版2019.1安装步骤(含激活码)
2019/10/09 Python
Python多继承以及MRO顺序的使用
2019/11/11 Python
python 解决flask 图片在线浏览或者直接下载的问题
2020/01/09 Python
Python3安装模块报错Microsoft Visual C++ 14.0 is required的解决方法
2020/07/28 Python
html5指南-6.如何创建离线web应用程序实现离线访问
2013/01/07 HTML / CSS
浅谈Html5移动端ios/Android兼容性总结
2018/06/01 HTML / CSS
文字自荐书范文
2014/02/10 职场文书
信访工作经验交流材料
2014/05/23 职场文书
过程装备与控制工程专业求职信
2014/07/02 职场文书
一份没有按时交货失信于客户的检讨书
2014/09/19 职场文书
新闻稿件写作技巧
2015/07/18 职场文书
初一军训感言
2015/08/01 职场文书
Shell脚本一键安装Nginx服务自定义Nginx版本
2022/03/20 Servers
ipad隐藏软件app图标方法
2022/04/19 数码科技
python和Appium的移动端多设备自动化测试框架
2022/04/26 Python