这是我参与更文挑战的第3天,活动详情查看: 更文挑战
一、背景介绍
什么是JavaScript30?JavaScript30 是 Wes Bos 推出的一个 30 天纯 JavaScript 编码挑战。该项目不仅提供了 30 天每一个视频教程,而且提供了文档和 30 个挑战的解决方案源代码,可谓是一应俱全了。旨在帮助我们用纯 JavaScript 来实战,真正的无框架,无编译器,无库和无引用。
官网是这样说的:
Build 30 things in 30 days with 30 tutorials
No Frameworks×No Compilers×No Libraries×No Boilerplate
罗列一下项目相关链接地址,后期不在赘述:
JavaScript30 挑战官网地址:javascript30.com/
JavaScript30 挑战github源码地址:github.com/wesbos/Java…
中文联系指南地址:github.com/soyaine/Jav…
二、目的
虽然网上也有相关的资料信息,但是自己还是想实践一下,记录一下自己的过程,查漏补缺,做一个挑战,同时增加自己的思考,毕竟敲代码这事,眼过千遍,不如手过一遍,看过再多,不如一遍一遍的自己去实现。
正如作者官网所说:
There is no formation without repetition.
三、储备知识
这里主要是指一些关于 ES6 的储备知识,从作者的最终代码里可以看出,作者使用了:
- const(声明只读常量,不可重复赋值)和模板字符串;
- forEach 和 箭头函数。
四、案例实现流程
这个模块是要模拟一个敲鼓的页面。当使用者在键盘上敲击 ASDFGHJKL 这几个按键时,页面上和键盘字母对应的按钮产生变化,出现亮圈和变大特效,同时对应的类似敲鼓的声音发出。
五、实现
首先,我们可以将 github 上面的源码下载到本地,然后我们会发现,每一个文件里边都有这样的两个文件。
最终代码
<script>
(function(){
window.addEventListener('keydown',playHandler)
function playHandler(e){
console.log(e);
//play music
const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
if(audio) {
audio.currentTime = 0;
audio.play();
}
//console.log('audio',audio);
//dom style
const dom = document.querySelector(`div[data-key="${e.keyCode}"]`);
if(dom) {
dom.classList.add('playing');
}
//console.log('dom',dom);
}
document.querySelectorAll('.key').forEach(key => {
key.addEventListener('transitionend',transitionHandler);
})
function transitionHandler(e){
console.log(e);
if(e.propertyName === 'transform'){
e.currentTarget.classList.remove('playing');
}
}
})()
</script>
复制代码
六、总结回顾
从上面的代码中可以看出,其实我们这个功能主要做了三件事:
添加键盘事件
播放对应声音效果
改变点击的样式效果
(function(){
window.addEventListener('keydown',playHandler)
function playHandler(e){
console.log(e);
//play music
//dom style
}
})()
复制代码
1.过程分解
- 键盘监听事件;
- 为 window 上添加 keydown(喜欢用 keyup 也可以) 键盘事件;
- 对应的事件处理,其中有:
(1)首先我获取了一下键盘事件上的按键键码;
比如F12
比如方向上按键
(2)使用 querySelector 获取元素(别问为什么用这,问就是方便);
(3)匹配 data-key 和对应键码的元素;
const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
const dom = document.querySelector(`div[data-key="${e.keyCode}"]`);
复制代码
(4)对元素进行处理,即播放声音、样式改变。
audio.play();
dom.classList.add('playing');
复制代码
当进行到这一步的时候,当然是没有完成的,现在有两个问题:
① 按键按了之后样式无法关闭;
② 当你打开控制台(F12)的时候,持续按住一个按键,比如 A,你会发现,有时候触发了,有时候没有触发。
③ 当我随便按一个别的按键的时候,它会报错。
- 给每一个 “.key” 添加 transitionend 事件。
在这里要注意, transitionend 事件有很多个属性。
我们通过代码来展示一下它的属性:
document.querySelectorAll('.key').forEach(key => {
key.addEventListener('transitionend',transitionHandler);
})
function transitionHandler(e){
console.log(e);
}
复制代码
在控制台我们可以看到它的多个属性:
七、重难点
1. 对应键盘按键和页面按钮
const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
const dom = document.querySelector(`div[data-key="${e.keyCode}"]`);
复制代码
2. 按键无法关闭,即页面按钮无法恢复原状
这里主要就是借助 transitionend 事件里边的 transform 属性,在每一次触发按键的时候,去除一次样式。
if(e.propertyName === 'transform'){
e.currentTarget.classList.remove('playing');
}
复制代码
3. 当按了键盘上别的按键的时候,报错
if(audio) {
audio.play();
}
if(dom) {
dom.classList.add('playing');
}
复制代码
4. 按住不放时,不会立即触发
这个问题只需要在每次播放声音之前,设置播放时间为 0 即可。
if(audio) {
//每次播放之前,设置时间为 0
audio.currentTime = 0;
audio.play();
}
复制代码
5. 题外话
大家有兴趣的可以去看看作者里边写的那个 kbd 的标签。虽然我们只需要补充 JavaScript 代码,但是对于已经写好的东西,我们要做一个充分的了解,不然我们也无法去做后续的事情。
今天就结束啦,马上就要放假了,祝大家假期愉快!