阅读 70

JavaScript 30天编码挑战——第 1 天

这是我参与更文挑战的第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 的储备知识,从作者的最终代码里可以看出,作者使用了:

  1. const(声明只读常量,不可重复赋值)和模板字符串;
  2. forEach 和 箭头函数。

四、案例实现流程

这个模块是要模拟一个敲鼓的页面。当使用者在键盘上敲击 ASDFGHJKL 这几个按键时,页面上和键盘字母对应的按钮产生变化,出现亮圈和变大特效,同时对应的类似敲鼓的声音发出。 未命名文件.png

五、实现

首先,我们可以将 github 上面的源码下载到本地,然后我们会发现,每一个文件里边都有这样的两个文件。

  • index-START.html     ————    这个是初始化的文档,里边写好了基本样的 html 和 css 样式,我们只需要编写 JavaScript 代码即可。
  • index-FINISHED.html    ————    那么这个肯定就是已经实现好的最后文档了,可以供我们查看最终效果和提供解决的思路。

    最终代码

    <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.过程分解

    1. 键盘监听事件;
    2. 为 window 上添加 keydown(喜欢用 keyup 也可以) 键盘事件;
    3. 对应的事件处理,其中有:

       (1)首先我获取了一下键盘事件上的按键键码;
          比如F12 image.png
          比如方向上按键 image.png    (2)使用 querySelector 获取元素(别问为什么用这,问就是方便);
       (3)匹配 data-key 和对应键码的元素;

    image.png

          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');
    复制代码

    当进行到这一步的时候,当然是没有完成的,现在有两个问题

    ① 按键按了之后样式无法关闭;

    image.png

    ② 当你打开控制台(F12)的时候,持续按住一个按键,比如 A,你会发现,有时候触发了,有时候没有触发。

    ③ 当我随便按一个别的按键的时候,它会报错。

    image.png

    1. 给每一个 “.key” 添加 transitionend 事件。

    在这里要注意, transitionend 事件有很多个属性。

    我们通过代码来展示一下它的属性:

    document.querySelectorAll('.key').forEach(key => {
                  key.addEventListener('transitionend',transitionHandler);
              })
              function transitionHandler(e){
                  console.log(e);
              }
    复制代码

    在控制台我们可以看到它的多个属性:

    image.png

    七、重难点

    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 代码,但是对于已经写好的东西,我们要做一个充分的了解,不然我们也无法去做后续的事情。




      今天就结束啦,马上就要放假了,祝大家假期愉快!

  • 文章分类
    前端
    文章标签