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 相关文章推荐
加速IE的Javascript document输出的方法
Dec 02 Javascript
js用Date对象处理时间实现思路及代码
Jan 31 Javascript
如何将php数组或者对象传递给javascript
Mar 20 Javascript
扩展jQuery对象时如何扩展成员变量具体怎么实现
Apr 25 Javascript
js弹出对话框方式小结
Nov 17 Javascript
jquery简单插件制作(fn.extend)完整实例
May 24 Javascript
微信小程序  modal弹框组件详解
Oct 27 Javascript
JavaScript实现定时页面跳转功能示例
Feb 14 Javascript
p5.js入门教程之图片加载
Mar 20 Javascript
node puppeteer(headless chrome)实现网站登录
May 09 Javascript
详解vuex中action何时完成以及如何正确调用dispatch的思考
Jan 21 Javascript
解决vue $http的get和post请求跨域问题
Jun 07 Vue.js
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
简单的过滤字符串中的HTML标记
2006/12/25 PHP
收藏的一个php小偷的核心程序
2007/04/09 PHP
PHP的Socket网络编程入门指引
2015/08/11 PHP
PHP获取不了React Native Fecth参数的解决办法
2016/08/26 PHP
php实现将二维关联数组转换成字符串的方法详解
2017/07/31 PHP
PHP实现PDO操作mysql存储过程示例
2019/02/13 PHP
模拟jQuery ajax服务器端与客户端通信的代码
2011/03/28 Javascript
ajax不执行success回调而是执行了error回调
2012/12/10 Javascript
jQuery中index()的用法分析
2014/09/05 Javascript
jQuery移动端日期(datedropper)和时间(timedropper)选择器附源码下载
2016/04/19 Javascript
Bootstrap如何激活导航状态
2017/03/22 Javascript
JavaScript实现焦点进入文本框内关闭输入法的核心代码
2017/09/20 Javascript
Bootstrap 3多级下拉菜单实例
2017/11/23 Javascript
Angular浏览器插件Batarang介绍及使用
2018/02/07 Javascript
element-ui 关于获取select 的label值方法
2018/08/24 Javascript
vue2.0 获取从http接口中获取数据,组件开发,路由配置方式
2019/11/04 Javascript
python创建只读属性对象的方法(ReadOnlyObject)
2013/02/10 Python
python访问系统环境变量的方法
2015/04/29 Python
Python爬虫获取整个站点中的所有外部链接代码示例
2017/12/26 Python
Python Tkinter模块实现时钟功能应用示例
2018/07/23 Python
对python 读取线的shp文件实例详解
2018/12/22 Python
Python使用Beautiful Soup爬取豆瓣音乐排行榜过程解析
2019/08/15 Python
python 回溯法模板详解
2020/02/26 Python
使用keras实现非线性回归(两种加激活函数的方式)
2020/07/05 Python
基于html5 canvas做批改作业的小插件
2020/05/20 HTML / CSS
Chain Reaction Cycles芬兰:世界上最大的在线自行车商店
2017/12/06 全球购物
委托书格式范文
2015/01/28 职场文书
承德避暑山庄导游词
2015/02/03 职场文书
2015年学雷锋活动总结
2015/02/06 职场文书
学校百日安全活动总结
2015/05/07 职场文书
企业战略合作意向书
2015/05/08 职场文书
电台广播稿范文
2015/08/19 职场文书
服务行业标语口号
2015/12/26 职场文书
2016高校自主招生自荐信范文
2016/01/28 职场文书
Docker 镜像介绍以及commit相关操作
2022/04/13 Servers
nginx访问报403错误的几种情况详解
2022/07/23 Servers