资讯专栏INFORMATION COLUMN

day1 - JavaScript Drum Kit 中文指南

HackerShell / 972人阅读

摘要:中文指南作者简介是推出的一个天挑战。页面基础布局标签定义键盘文本说到技术概念上的特殊样式时,就要提到标签。主要代码主要属性有以下几个中有一个样式为,在本案例中,就是,是以中的为参照物,就是。

Day01 - JavaScript Drum Kit 中文指南

作者:©liyuechun
简介:JavaScript30 是 Wes Bos 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 1 篇。完整指南在 从零到壹全栈部落。

简介

第一天的练习是用JS制作一个爵士鼓的页面,通过敲击键盘上不同的字母,会发出不同的声音,并且页面上会伴随着敲击的动画。

效果如下:

想要实现以上效果,大致思路和解决方案如下:

检测到键盘上什么键被按下--监听keydown事件

在按键被按下的时候,播放音效--audio.play()

在按键被按下的同时,播放动画--Element.classList.add("playing")

在动画结束后,移除动画,不然之后再点击不会有任何效果--Element.classList.remove("playing")

基础语法 一些 ES6 语法

const :声明一个只读的常量,标识符的值只能赋值一次。

`字符串 ${ 变量、属性名 } `:模板字面量(Template literals)中用于表示模板字符串的标识。特点是字符串首尾用反引号(`),内部的模板部分用 ${ } 括起来表示,具体请看MDN文档。简单例子如下:

var a = 1;
var b = 2;
//不用模板的写法
console.log("三是" + (a + b) + "不是" + (2 * a + b)); //"三是3不是4"
//使用模板字符串的写法
console.log(`三是${a + b}不是${2 * a + b}`); //"三是3不是4"
forEach 与箭头函数

使用 document.querySelector 获取一组符合 CSS 选择符的元素快照,类型为 NodeList(此对象是对于文档的实时运行的动态查询),对其进行遍历时可采用 forEach 方法。

// Code from http://es6-features.org/#StatementBodies

// ES6
nums.forEach(v => {
    if (v % 5 === 0)
        fives.push(v);
})

// ES5
nums.forEach(function (v) {
    if (v % 5 === 0)
        five.push(v);
})
页面基础布局




  
  JS Drum Kit
  





  
A clap
S hihat
D kick
F openhat
G boom
H ride
J snare
K tom
L tink

标签定义键盘文本

说到技术概念上的特殊样式时,就要提到 标签。正如你已经猜到的,它用来表示文本是从键盘上键入的。
浏览器通常用等宽字体来显示该标签中包含的文本。
标签经常用在于计算机相关的文档和手册中。例如:

键入 quit 来退出程序,或者键入 menu 来返回主菜单。

使用 data-* 属性来嵌入自定义数据

页面里通过data-key将页面展示的内容和audio关联起来。使用方法如下介绍:

  • Owl
  • Salmon
  • Tarantula

① data-* 属性用于存储页面或应用程序的私有自定义数据。
② data-* 属性赋予我们在所有 HTML 元素上嵌入自定义 data 属性的能力。
③ 属性名不应该包含任何大写字母,并且在前缀 "data-" 之后必须有至少一个字符
④ 属性值可以是任意字符串

语法:

属性值:

描述
somevalue 规定属性的值(以字符串)。
主要CSS代码
html {
  font-size: 10px;
  background: url(http://i.imgur.com/b9r5sEL.jpg) bottom center;
  background-size: cover;
}
body,
html {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
}

.keys {
  display: flex;
  flex: 1;
  min-height: 100vh; 
  align-items: center;  
  justify-content: center; 
}

.key {
  border: .4rem solid black;
  border-radius: .5rem;
  margin: 1rem;
  font-size: 1.5rem;
  padding: 1rem .5rem;
  transition: all .07s ease;
  width: 10rem;
  text-align: center;
  color: white; 
  background: rgba(0, 0, 0, 0.4);
  text-shadow: 0 0 .5rem black;
}

.playing {
  transform: scale(1.1);
  border-color: #ffc600;
  box-shadow: 0 0 1rem #ffc600;
}

kbd {
  display: block; 
  font-size: 4rem;
}

.sound {
  font-size: 1.2rem;
  text-transform: uppercase;
  letter-spacing: .1rem;
  color: #ffc600;
}

主要属性有以下几个:

html中有一个样式为font-size: 10px;,在本案例中,1rem就是10px,rem是以html中的font-size为参照物,1.2rem就是12px

transform: scale(1.1);--该属性在键盘被点击时将该元素缩放至原来的1.1倍。

.key{border: .4rem solid black;} .playing{border-color: #ffc600;}--这两条属性在按键点击的时候改变边框颜色。

.key{text-shadow: 0 0 .5rem black;} .playing{box-shadow: 0 0 1rem #ffc600;}--这两条属性在按键点击的时候改变阴影的效果

transition: all .07s ease;--定义以上动画在0.07秒内完成。
我们注意到我们定义了.palying类,在按键按下的时侯为该元素添加playing类,在结束后移除playing类。

JS代码 按键监听&音效播放&添加动画
function playSound(e) {
    const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
    const key = document.querySelector(`div[data-key="${e.keyCode}"]`);
    if (!audio) return;
    
    key.classList.add("playing");
    audio.currentTime = 0;
    audio.play();
}
/**
* 监听页面的keydown事件,触发playAudio函数。
*/
window.addEventListener("keydown", playSound);

监听页面的keydown事件,触发playAudio函数。

通过KeyCode检测我们按下的键盘按钮是哪个按钮。

A -> 65

B -> 66

C -> 67

D -> 68

E -> 69

F -> 70

G -> 71

H -> 72

I -> 73

J -> 74

K -> 75

L -> 76

M -> 77

N -> 78

O -> 79

P -> 80

Q -> 81

R -> 82

S -> 83

T -> 84

U -> 85

V -> 86

W -> 87

X -> 88

Y -> 89

Z -> 90

http://keycode.info打开这个网站,可以轻松查看键盘的按钮对应的code。

在这里我们用到了ES6的模板字符串,${e.keyCode},可以动态的将按键的Keycode传过去,以使audio动态的获取每一个按键绑定的audio。需要注意的是模板字符串一定要使用"`"(Esc下面那个键)包裹,而不是双引号。

我们注意到audio.play();前面一行是audio.currentTime = 0;,这是因为,如果没有在播放音效前将该音乐重置,会发生以下情况,当我连续点击某一按键的时候,只有第一次点击会响,第二次第三次连续的点击可能没声音。所以在每一次点击之前重置音效是很有必要的。

key.classList.add("playing");可以在按键点击的同时为该元素添加playing类,展示小动画。

if(!audio) return; if(!key) return;因为并不是每一个按键都有音效,当用户点击了非绑定音效按键,及时退出函数是很好的习惯。

动画结束后移除动画
function stopTransition(e) {
    if (e.propertyName !== "transform") return;
    e.target.classList.remove("playing");
}
  
const keys = Array.from(document.querySelectorAll(".key"));
keys.forEach(key => key.addEventListener("transitionend",stopTransition));  

监听每一个按键元素的transitionend事件,当按键元素的动画结束后会触发stopTransition函数。

首先在stopTransition函数中可以输出事件e的内容,会输出该动画每一步具体的变化,发现其中会有propertyName属性,可以通过判断propertyName等于其中的一个值(例如"transform"),等于该值就移除playing类,也即移除动画。

在定位元素的时候,可以使用this也可以使用e.target,可以简单这么理解,this值的是谁出发了这次事件,也就是key,就等同于事件的目标(e.target).

解决难点 如何将键盘按键与页面按钮对应起来?

连接的帮手是 keydown 事件中的 keyCode 属性,keyCode 属性的值和 ASCII 编码值相同(对应小写字母)。在这个网站可以用按键盘来查看对应的键码。

我们能获取到的初始页面中,按钮 div 和音频 audio 标签中都添加了一个属性 data-key 用于存储对应的键码,这样做的目的是,添加键盘事件监听后,触发键盘事件时即可获取事件的 keyCode 属性值,以此为线索,操作对应的按钮及音频。

const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
const key = document.querySelector(`div[data-key="${e.keyCode}"]`);
如何保证按键被按住不放时,可以马上响起连续鼓点声?

每次播放音频之前,设置播放时间戳为 0:

const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
audio.currentTime = 0;
audio.play();
如何使页面按钮恢复原状?

利用一个叫 transitionened 的事件,它在 CSS transition 结束后会被触发。我们就可以利用这个事件,在每次打鼓的效果(尺寸变大、颜色变化)完成之后,去除相应样式。

在这个页面中,发生 transition 的样式属性不止一个(box-shadow, transform, border-color),所以需要添加一个判断语句,使每发生一次按键事件时,只去除一次样式。

funciton remove(event) {
  if (event.propertyName !== "transform") return;
  this.classList.remove("playing");
  // event.target.classList.remove("playing");
}
完整源码

Github Source Code

扫码申请加入全栈部落

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/84066.html

相关文章

  • Day07 - Array Cardio 中文指南

    摘要:中文指南二作者简介是推出的一个天挑战。完整中文版指南及视频教程在从零到壹全栈部落。第七天的练习是接着之前中文指南一的练习,继续熟练数组的方法,依旧没有页面显示效果,所以请打开浏览器的面板进行调试运行。 Day07 - Array Cardio 中文指南二 作者:©liyuechun 简介:JavaScript30 是 Wes Bos 推出的一个 30 天挑战。项目免费提供了 30 个...

    Forest10 评论0 收藏0
  • JavaScript 30 - 一起做一次了不起的挑战

    摘要:加入我们,一起挑战吧扫码申请加入全栈部落 JavaScript 30 - 一起做一次了不起的挑战 (Node+Vue+微信公众号开发)企业级产品全栈开发速成周末班首期班(10.28号正式开班,欢迎抢座) 在Github上看到了wesbos的一个Javascript30天挑战的repo,旨在使用纯JS来进行练习,不允许使用任何其他的库和框架,该挑战共30天,我会在这里复现这30天遇到的挑...

    1treeS 评论0 收藏0
  • 2017-07-01 前端日报

    摘要:前端日报精选腾讯前端团队社区源码分析入门指南一些关于使用的心得基本类型与引用类型知多少掘金中文第期框架选型周刊第期入门系列模块车栈重构基于的网络请求库某熊的全栈之路的那些奇技淫巧的平凡之路模仿写个数组监听掘 2017-07-01 前端日报 精选 Why you shouldn`t use Preact, Fast-React, etc. to replace React today -...

    _DangJin 评论0 收藏0
  • Python知识点整理(day1

    摘要:上一步中执行时,明确的指出脚本由解释器来执行。为了表示更多的中文汉字有了,但是,中华文化博大精深,发现不够用,因此有了对的扩展即。但是,用编码对于英文只占一个字节,,一个中文汉字在却占三个字节可能是中国人有钱啊,我大天朝。 简介: Python是一种解释型语言,需要解释器来执行。可以通过在IDLE下执行,也可以在文本文件里写入代码,然后将该文件命名为xx.py 然后在Windows下可...

    Luosunce 评论0 收藏0

发表评论

0条评论

HackerShell

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<