You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Wes Bos鼓组项目:移除playing类功能失效求助

问题:原生JS鼓组项目中无法移除'playing'类

我正在跟随Wes Bos的原生JS视频开发鼓组项目,目前遇到移除类的问题:添加'playing'类正常,但切换该类的功能失效,过渡效果持续保留。removeTransition函数内的console.log无输出,且我已将keyCode修正为code。

当前代码

JavaScript

document.addEventListener('keydown', function(e) {
const audio = document.querySelector(`audio[data-key="${e.code}"]`); // attribute selector
const key = document.querySelector(`.key[data-key="${e.code}"]`)
if(!audio) return;
audio.currentTime = 0; 
audio.play();
key.classList.add('playing');
});

function removeTransition(e) {
    if (e.propertyName !== 'transform') return;
    e.target.classList.toggle('playing');
  }

const keys = document.querySelectorAll('.key');
keys.forEach(key => key.addEventListener('transitionEnd', removeTransition));

CSS

.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;
}

HTML

<div class="keys">
    <div data-key="KeyA" class="key">
      <kbd>A</kbd>
      <span class="sound">clap</span>
    </div>
    <div data-key="KeyS" class="key">
      <kbd>S</kbd>
      <span class="sound">hihat</span>
    </div>
    <div data-key="KeyD" class="key">
      <kbd>D</kbd>
      <span class="sound">kick</span>
    </div>
    <div data-key="KeyF" class="key">
      <kbd>F</kbd>
      <span class="sound">openhat</span>
    </div>
    <div data-key="KeyG" class="key">
      <kbd>G</kbd>
      <span class="sound">boom</span>
    </div>
    <div data-key="KeyH" class="key">
      <kbd>H</kbd>
      <span class="sound">ride</span>
    </div>
    <div data-key="KeyJ" class="key">
      <kbd>J</kbd>
      <span class="sound">snare</span>
    </div>
    <div data-key="KeyK" class="key">
      <kbd>K</kbd>
      <span class="sound">tom</span>
    </div>
    <div data-key="KeyL" class="key">
      <kbd>L</kbd>
      <span class="sound">tink</span>
    </div>
  </div>

  <audio data-key="KeyA" src="sounds/clap.wav"></audio>
  <audio data-key="KeyS" src="sounds/hihat.wav"></audio>
  <audio data-key="KeyD" src="sounds/kick.wav"></audio>
  <audio data-key="KeyF" src="sounds/openhat.wav"></audio>
  <audio data-key="KeyG" src="sounds/boom.wav"></audio>
  <audio data-key="KeyH" src="sounds/ride.wav"></audio>
  <audio data-key="KeyJ" src="sounds/snare.wav"></audio>
  <audio data-key="KeyK" src="sounds/tom.wav"></audio>
  <audio data-key="KeyL" src="sounds/tink.wav"></audio>
解决方案

你的问题出在两个核心点:

  1. 事件名称拼写错误:你绑定的是transitionEnd,但标准DOM事件名是小写的transitionend(最后一个字母e为小写)。这个错误直接导致过渡结束时不会触发removeTransition函数,所以日志无输出、类无法移除。
  2. toggle方法使用不当:过渡结束时我们只需要移除playing类,而非切换状态。如果用toggle,用户在过渡结束前重复按键会导致类状态混乱,应改为e.target.classList.remove('playing')。

另外,为兼容部分浏览器返回带前缀的propertyName(如webkitTransform),可以把判断条件改为模糊匹配:

if (!e.propertyName.includes('transform')) return;

修正后的JavaScript代码:

document.addEventListener('keydown', function(e) {
const audio = document.querySelector(`audio[data-key="${e.code}"]`);
const key = document.querySelector(`.key[data-key="${e.code}"]`)
if(!audio) return;
audio.currentTime = 0; 
audio.play();
key.classList.add('playing');
});

function removeTransition(e) {
    if (!e.propertyName.includes('transform')) return;
    e.target.classList.remove('playing');
  }

const keys = document.querySelectorAll('.key');
keys.forEach(key => key.addEventListener('transitionend', removeTransition));

内容的提问来源于stack exchange,提问作者Brendha Tasca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 12:07:06