不做码农而做 DJ 😎

😎Coding 一定很累吧,快来跟我一起 Djing !!!😎

我的思路是通过监听键盘按下 事件,在用户按下对应键时,找到相应的按键元素音频元素 ,通过添加和移除 CSS 类实现按键效果,并播放关联的音频文件。同时,通过事件监听器确保在按键元素的过渡动画 结束时,移除添加的类,实现按键效果的平滑消失

话不多说,上代码!😘


HTML 框架 ❤

我们在页面上添加一行按键(A-L),每个按键对应不同的乐器,再用audio元素存放音频存放地址,和对应按键的键盘码,以便于后续 JS 实现。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>做个快乐的DJ</title>
    <link rel="stylesheet" href="./common.css">
</head>
<body>
    <div class="keys">
        <div class="key" data-key="65">
            <div>A</div>
            <span class="sound">clap</span>
        </div>
        <div class="key" data-key="83">
            <div>S</div>
            <span class="sound">hihat</span>
        </div>
        <div class="key"  data-key="68">
            <div>D</div>
            <span class="sound">kick</span>
        </div>
        <div class="key"  data-key="70">
            <div>F</div>
            <span class="sound">openhat</span>
        </div>
        <div class="key"  data-key="71">
            <div>G</div>
            <span class="sound">boom</span>
        </div>
        <div class="key"  data-key="72">
            <div>H</div>
            <span class="sound">ride</span>
        </div>
        <div class="key"  data-key="74">
            <div>J</div>
            <span class="sound">snare</span>
        </div>
        <div class="key"  data-key="75">
            <div>K</div>
            <span class="sound">tom</span>
        </div>
        <div class="key" data-key="76">
            <div>L</div>
            <span class="sound">tink</span>
        </div>
    </div>
    <audio src="./sounds/clap.wav" data-key="65"></audio>
    <audio src="./sounds/hihat.wav" data-key="83"></audio>
    <audio src="./sounds/kick.wav" data-key="68"></audio>
    <audio src="./sounds/openhat.wav" data-key="70"></audio>
    <audio src="./sounds/boom.wav" data-key="71"></audio>
    <audio src="./sounds/ride.wav" data-key="72"></audio>
    <audio src="./sounds/snare.wav" data-key="74"></audio>
    <audio src="./sounds/tom.wav" data-key="75"></audio>
    <audio src="./sounds/tink.wav" data-key="76"></audio>
<script src="./index.js"></script>
</body>
</html>

简单介绍一下:

  • <div class="keys"> : 包含所有敲击乐按键的容器。
  • <div class="key" data-key="xx"> : 单个按键元素,包括按键显示的字母和音频描述,data-key属性存放按键的键盘码。
  • <audio> : 包含音频文件路径和与之关联的按键。

CSS 样式 🧡

CSS 样式包含两个部分,重置样式业务样式

css 复制代码
/* CSS Reset 重置样式*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
}
article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
    display: block;
}
body {
    line-height: 1;
}
ol, ul {
    list-style: none;
}
blockquote, q {
    quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
    content: '';
    content: none;
}
table {
    border-collapse: collapse;
    border-spacing: 0;
}

/*业务样式*/
html{
    height: 100vh;
    font-size: 10px;
    background: url('./background.png') bottom center;/*载入图片*/
    background-size: cover; /*让图片覆盖窗口*/
}
body, html{
    font-family: sans-serif;
}
.keys{
    display: flex; 
    align-items: center;
    justify-content: center;/*元素居中*/
    min-height: 100vh;
}
.key{
    border: 0.4rem solid rgb(1, 60, 106);
    border-radius: 0.5rem;
    margin: 1rem;
    font-size: 1.5rem;
    padding: 1rem 0.5rem;
    transition:all 0.7s ease;
    width:10rem;
    text-align: center;
    color: rgb(6, 55, 94);
    box-shadow: 0 0 2rem rgb(0, 75, 121)

}
.playing{ /*触发按键效果*/
    transform: scale(1.1);
    border-color: rgb(248, 117, 117);
    box-shadow: 0 0 2rem rgb(255, 84, 84)
}
.key div{
    font-size: 4rem;
}
.sound{
    font-size: 1.2rem;
    text-transform: uppercase;
    letter-spacing: normal;
    color: rgb(0, 145, 143);
}

简单介绍一下:

  1. 重置样式:

    • 设置了各种 HTML 元素的默认样式,例如清除列表项、删除引用等,以确保在不同浏览器中获得一致的基本外观。就不过多赘述了。
  2. 业务样式:

    • rem 是相对于根元素(html 元素)字体大小的单位。这里我们设置默认的根元素字体大小为 10 px,那么.key类的字体大小 1.5 rem 即为15 px。
    • .key 类定义了按键的基本样式,包括边框、圆角、阴影、字体大小等。其中transition:all 0.7s ease;这行代码表示所有样式属性在变化时都会以持续 0.7 秒的时间,并采用渐变的速度曲线,从而产生平滑的过渡效果。
    • .playing 类定义了按键在播放音频时的样式,增加了缩放和边框颜色的变化,以及阴影效果。其中transform: scale(1.1);表示将元素沿着 X 和 Y 方向同时放大到原始大小的 1.1 倍,使交互更加生动有趣。通过 JS 对这个类的添加和移除,实现按键打击效果,直接化身 DJ 。

JS 实现 💛

js 复制代码
// 播放音频和添加按键效果的函数
function playSound(e) {
    const keyCode = e.keyCode;
    const key = document.querySelector(`.key[data-key="${keyCode}"]`);//匹配按键
    
    // 如果按键存在,添加 playing 类
    key && key.classList.add('playing');
    const audio = document.querySelector(`audio[data-key="${keyCode}"]`);//匹配音频
    
    // 如果音频存在,重置播放时间并播放音频
    audio && (audio.currentTime = 0, audio.play());
}
// 获取所有带有 .key 类的元素
const keys = Array.from(document.querySelectorAll('.key'))
// 对每个按键添加 transitionend 事件监听器
keys.forEach(key => {
    key.addEventListener('transitionend', function(e) {
        // 如果触发的事件不是 transform,则返回
        if (e.propertyName !== 'transform') return;
        // 移除 playing 类
        this.classList.remove('playing');
    })
})
// 添加全局键盘按下事件监听器,触发 playSound 函数
window.addEventListener('keydown', playSound)

我们挑出几个重点讲讲:

document.querySelector(`.key[data-key="${keyCode}"]`):

  1. 反引号(` `) 是 ES6 引入的模板字面量。它允许你在字符串中嵌入变量。${keyCode} 就是其中的变量插值,这里用来替换为实际的按键码值。
  2. .key[data-key="${keyCode}"] 表示一个 CSS 选择器字符串 。它表示选择具有 key 类且具有 data-key 属性值等于 keyCode 的元素。
  3. document.querySelector() 是一个 DOM 操作方法,用于在文档中选择第一个匹配指定选择器的元素。在这里,它选择了具有指定 data-key 属性值的按键元素。

keys.forEach(key => {...}):

  1. key.addEventListener('transitionend', function(e) {...}) :对每个按键元素添加一个事件监听器,监听过渡动画结束事件
  2. if (e.propertyName !== 'transform') return; : 判断事件的 propertyName 属性是否为 'transform',如果是,执行后续的操作,如果不是,则直接返回。
  3. this.classList.remove('playing'); : 如果过渡动画是针对 transform 属性的,那么用 classList.remove 方法从当前元素的类列表中移除名为 'playing' 的类,以使按键效果消失。

综合起来,这段代码确保在每个按键元素上的过渡动画结束时,只处理与 transform 属性相关的事件,以移除添加的 'playing' 类,从而产生按键效果的消失过渡。

最后 🦄

Coding 很有趣,闲暇之余,试试 DJing 吧!

已将代码、图片及乐器 wav 文件放到 Gitee,感兴趣的同学可以自取,Coding不易,切勿白嫖!记得点亮 star !!!

技术小白记录学习过程,有错误或不解的地方还请评论区留言,如果这篇文章对你有所帮助请 "点赞 收藏+关注" ,感谢支持!!

相关推荐
Raink老师10 分钟前
1.3 如何安装 TypeScript?
前端·javascript·typescript
ST_小罗27 分钟前
【Web前端】JavaScript入门与基础(二)
开发语言·前端·javascript
Greatlifeee36 分钟前
VUE3+TS实现图片缩放移动弹窗
前端·javascript·vue.js
笔直向前冲40 分钟前
el-table控制type=“expand“展开列 根据条件显示或隐藏展开按钮
javascript·vue.js·elementui
萧萧风44 分钟前
在Vue3 + Vite 项目安装使用 Tailwind CSS 4.0报错
前端·css
theMuseCatcher1 小时前
手写ES6 Promise() 相关函数
javascript·es6
忘不了情2 小时前
vue2中,codemirror编辑器的使用
前端·javascript·编辑器
diygwcom2 小时前
功能强大且易于使用的 JavaScript 音频库howler.js 和AI里如何同时文字跟音频构思想法
开发语言·javascript·音视频
坚定信念,勇往无前3 小时前
threejs 四元数(Quaternion)和欧拉角(Euler)学习
javascript·学习
软件技术NINI3 小时前
html css js网页制作成品——HTML+CSS+js宁夏银川网页设计(5页)附源码
javascript·css·html