当 JavaScript 听到键盘声:一场关于按键与光影的前端实验

197 阅读9分钟

用 HTML5 做一个「敲击乐」:从静态页面到动态交互

一、项目介绍

“HTML5 敲击乐(Drum Kit)” 是一个非常经典的入门练习。它的目标是:当用户按下键盘上的某个键(如 A、S、D、F...),页面上的相应按键高亮,同时播放一个打击乐音效。

这个项目非常小,却包含了前端开发的所有核心知识点:

  • HTML: 页面结构与语义化标签
  • CSS: 视觉布局与动画效果
  • JavaScript: 事件监听与 DOM 操作

通过这个项目,我们能完整体会从静态页面到动态交互的整个过程。


二、HTML:结构是根

HTML 是网页的“骨架”。在这个项目里,我们定义了 9 个键位,每个键位对应一个字母(A-L)与一个声音名称。

<div class="keys">
    <div class="key" data-key="65">
        <h3>A</h3>
        <span class="sound">clap</span>
    </div>
    <div class="key" data-key="83">
        <h3>S</h3>
        <span class="sound">hihat</span>
    </div>
    <div class="key" data-key="68">
        <h3>D</h3>
        <span class="sound">kick</span>
    </div>
    ...
</div>

结构解析:

  • .keys:是容器,用于包裹所有的打击键。
  • .key:是单个打击键的盒子。
  • data-key:自定义数据属性,用来存储键盘按键的编码(keyCode)。
    当我们在 JavaScript 中监听 keydown 事件时,可以通过这个属性快速匹配对应的元素。
  • <h3> 显示字母,<span class="sound"> 显示音效名称。

这种结构清晰、语义明确,为后续的 CSS 布局与 JS 动态交互打下了良好的基础。


三、CSS:样式是灵魂

HTML 提供结构,而 CSS 赋予页面视觉表现。

1. CSS Reset —— 消除浏览器差异

每个浏览器对 HTML 元素的默认样式都不同,比如标题大小、段落间距等。为了让页面在所有浏览器中统一展示,我们通常使用 Reset CSS

/* Eric Meyer's Reset CSS v3.0 */
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, i, u, 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: inherit;
  vertical-align: baseline;
}

Reset 的目的是“清零”所有默认样式,让我们能从一个统一的起点开始。

另外还补充了常见的现代全局设置:

*, *::before, *::after {
  box-sizing: border-box;
}
img {
  max-width: 100%;
  display: block;
}
a {
  text-decoration: none;
  color: inherit;
}

2. 页面背景与布局

我们希望页面在不同设备上都能自适应居中,所以使用了现代布局方式——Flexbox

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

解释:

  • display: flex; 让容器成为弹性盒子,子元素会自动排成一行。
  • justify-content: center; 水平居中。
  • align-items: center; 垂直居中。
  • min-height: 100vh; 表示高度占满整个视窗。

背景使用了一张图片:

html {
    font-size: 10px;
    background: url(./background.png) bottom center no-repeat;
    background-size: cover;
}

cover 会让图片等比例放大或缩小,覆盖整个页面。


3. 按键样式

每个 .key 盒子看起来像一个立体的按键:

.key {
    border: .4rem solid black;
    margin: 1rem;
    font-size: 1.5rem;
    padding: 1rem 0.5rem;
    width: 10rem;
    text-align: center;
    color: white;
    background: rgba(0,0,0,0.4);
    text-shadow: 0 0 .5rem black;
}
.key h3 {
    font-size: 4rem;
}
.key .sound {
    font-size: 1.2rem;
    color: #ffc600;
    text-transform: uppercase;
}
  • 使用 rem 单位,使页面在不同设备上能按比例缩放。
  • rgba(0,0,0,0.4) 提供了半透明的背景。
  • text-shadow 让文字有轻微发光效果。

4. 动画效果

当用户按下键盘时,我们会给对应的 .key 添加一个类名 playing

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

这段代码让按键瞬间放大,并带上发光的边框效果,营造出“被敲击”的视觉反馈。


四、JavaScript:让页面动起来

HTML 和 CSS 只能实现静态页面,要想让用户交互生效,就需要 JavaScript。

1. 事件监听

JavaScript 可以监听键盘事件。例如:

document.addEventListener('DOMContentLoaded', function() {
    function playSound(event) {
        let keyCode = event.keyCode;
        let element = document.querySelector('.key[data-key="'+keyCode+'"]');
        if (!element) return; // 防止按下无效键时报错
        element.classList.add('playing');
    }
    window.addEventListener('keydown', playSound);
});
  • DOMContentLoaded:保证 HTML 结构加载完成后再执行脚本。
  • event.keyCode:获取按下的键的编码。
  • querySelector('.key[data-key="65"]'):动态选择对应按键。
  • classList.add('playing'):为元素添加类,从而触发 CSS 动画。

2. 动画结束后移除样式

可以监听 transitionend 事件,在动画结束时移除 playing 类,让按钮恢复原状:

const keys = document.querySelectorAll('.key');
keys.forEach(key => key.addEventListener('transitionend', () => {
    key.classList.remove('playing');
}));

五、响应式与现代单位

在项目中使用了 remvh 两种相对单位:

  • rem:相对于根元素(html)的字体大小,常用于文字与盒子尺寸。
  • vh:相对于视窗高度,100vh 即占满整个屏幕。

这种做法可以保证页面在手机、平板、电脑上都有良好的显示效果。


六、总结

通过这个小项目,我们学到了:

  1. HTML 的结构化设计:通过合理的标签与自定义属性组织页面。
  2. CSS 的现代布局:使用 Flexbox 实现弹性居中,利用相对单位适配不同设备。
  3. JS 的交互逻辑:监听事件、操作 DOM、控制样式变化。
  4. 前端性能与工程意识:模块化分工、非阻塞加载、Reset CSS、语义化标签。

这就是一个前端开发者日常的核心任务:

用 HTML 构建结构,用 CSS 美化视觉,用 JavaScript 让页面活起来。

从静态到动态,从结构到交互,你已经完成了一次完整的 Web 应用开发闭环。
下一步,可以尝试给每个键加上音效文件,例如:

<audio data-key="65" src="sounds/clap.wav"></audio>

再用 JavaScript 播放声音,实现真正的“敲击乐”体验!


是否希望我帮你把这篇文章改成适合发布在 稀土掘金专栏 的排版版本(带 Markdown 标题层级、摘要与标签)?
我可以帮你生成适合掘金格式的版本,包括简介与推荐分类(如「前端基础」「HTML5 项目实战」)。

您说:

稀土掘金专栏

ChatGPT 说:

非常好 👍 那小G就帮你把这篇文章改写成适合发布在 稀土掘金专栏(掘金专栏) 的正式稿格式:

包含以下要素:

  • 合理的 Markdown 排版
  • 吸引人的标题
  • 简洁专业的导语(简介)
  • 推荐专栏分类建议
  • 编辑摘要(便于发布时填写)

🚀 用 HTML5 做一个「敲击乐」:从静态页面到动态交互

🎧 从 HTML + CSS 构建静态页面,到用 JavaScript 实现键盘互动,这个小项目带你完整体验前端开发的核心流程。


一、项目介绍

“HTML5 敲击乐(Drum Kit)” 是一个非常经典的前端入门练习。它的目标是:当用户按下键盘上的某个键(如 A、S、D、F...),页面上对应的按键会高亮显示,并播放打击乐音效。

这个项目虽小,却涵盖了完整的前端开发流程:

  • HTML: 定义结构
  • CSS: 负责样式与布局
  • JavaScript: 实现交互逻辑

二、HTML:网页的骨架

HTML 是网页的结构基础。在这个项目中,我们定义了 9 个按键,每个按键由一个字母和一个音效名称组成。

<div class="keys">
  <div class="key" data-key="65">
    <h3>A</h3>
    <span class="sound">clap</span>
  </div>
  <div class="key" data-key="83">
    <h3>S</h3>
    <span class="sound">hihat</span>
  </div>
  <div class="key" data-key="68">
    <h3>D</h3>
    <span class="sound">kick</span>
  </div>
  ...
</div>

🔍 结构解析

  • .keys:容器,用于包裹所有打击键。
  • .key:单个按键元素。
  • data-key:自定义属性,用于标识键盘按键编码(KeyCode)。
  • <h3>:显示键盘字母。
  • <span class="sound">:显示声音名称。

这种结构清晰、语义化强,为后续的 CSS 与 JavaScript 打下了坚实的基础。


三、CSS:赋予页面生命的样式

1. CSS Reset —— 消除浏览器差异

不同浏览器有默认样式差异,为了保证一致性,我们使用 Eric Meyer's Reset CSS 清除默认样式。

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, i, u, 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: inherit;
  vertical-align: baseline;
}

此外补充现代全局样式:

*, *::before, *::after {
  box-sizing: border-box;
}
img {
  max-width: 100%;
  display: block;
}

2. 页面背景与弹性布局

html {
  font-size: 10px;
  background: url(./background.png) bottom center no-repeat;
  background-size: cover;
}

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

🔹 关键点解释:

  • display: flex;.keys 成为弹性容器,子元素自动横向排列。
  • align-items: center; 垂直居中。
  • justify-content: center; 水平居中。
  • min-height: 100vh; 高度自适应屏幕。

Flexbox 是现代前端布局的核心利器,特别适合移动端和响应式布局。


3. 按键样式

.key {
  border: .4rem solid black;
  margin: 1rem;
  font-size: 1.5rem;
  padding: 1rem 0.5rem;
  width: 10rem;
  text-align: center;
  color: white;
  background: rgba(0,0,0,0.4);
  text-shadow: 0 0 .5rem black;
}
.key h3 {
  font-size: 4rem;
}
.key .sound {
  font-size: 1.2rem;
  color: #ffc600;
  text-transform: uppercase;
}

通过半透明背景 (rgba) 和 text-shadow,我们营造了类似打击乐面板的立体视觉感。


4. 动画反馈

按键按下时,我们通过添加 .playing 类名触发动画:

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

这样,按键会瞬间放大并闪烁光效,带来极佳的交互体验。


四、JavaScript:让网页动起来

JavaScript 是网页的“灵魂”,负责监听用户行为、操作 DOM。

1. 监听键盘事件

document.addEventListener('DOMContentLoaded', function() {
  function playSound(event) {
    let keyCode = event.keyCode;
    let element = document.querySelector('.key[data-key="'+keyCode+'"]');
    if (!element) return;
    element.classList.add('playing');
  }
  window.addEventListener('keydown', playSound);
});
  • DOMContentLoaded 确保在 DOM 加载完后再执行代码。
  • event.keyCode 获取键盘按键编码。
  • querySelector('.key[data-key="65"]') 动态匹配对应元素。
  • classList.add('playing') 触发 CSS 动画。

2. 动画结束后移除样式

const keys = document.querySelectorAll('.key');
keys.forEach(key => key.addEventListener('transitionend', () => {
  key.classList.remove('playing');
}));

防止动画状态停留,让按键在交互后自动恢复原状。


五、响应式单位:rem 与 vh

在本项目中,CSS 主要使用相对单位:

  • rem:相对于根元素(html)的字体大小。
  • vh:相对于视窗高度。

这两者能有效解决不同设备屏幕尺寸差异,适配手机和平板。


六、总结

通过这个项目,你学习并实践了前端开发的三个核心要素:

技术职责核心要点
HTML页面结构语义化标签、data 属性
CSS样式与布局Flex 居中、Reset CSS、动画效果
JS行为与交互事件监听、DOM 操作、类名切换

一个完整的前端项目往往遵循这样的流程:

结构 → 样式 → 交互 → 优化

从静态页面到动态交互,你已经完成了一个小型前端应用的完整闭环。


✨ 延伸挑战

你可以进一步为每个键添加音频,实现真正的“敲击乐”体验:

<audio data-key="65" src="sounds/clap.wav"></audio>

并在 playSound() 函数中加入播放逻辑:

const audio = document.querySelector('audio[data-key="'+keyCode+'"]');
if (!audio) return;
audio.currentTime = 0; // 重置音频时间
audio.play();

这样,你的网页就不仅仅“闪光”,还能“发声”!