css 类被永久添加到按钮

时间:2021-05-30 08:38:25

标签: javascript css addeventlistener

我有一段用于播放音频的 Drumkit 项目代码,并向按下的按钮添加过渡效果。试试这里drumkitProject

CSS

.key {
  border: .4rem solid black;
  border-radius: 10%;
  margin:1rem; 
    font-size: 1.5rem;
  padding: 1rem .5rem;
  transition: all .07s;
  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;
}

Javascript

function playSound(e) {
        const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);

        const pressedKey = document.querySelector(
          `.key[data-key="${e.keyCode}"]`
        );

        if (!audio) return;

        pressedKey.classList.add("playing");

        audio.currentTime = 0;
        audio.play();
      }

      function stopSound(e) {
        if (e.propertyName !== "transform") return;
        this.classList.remove("playing");
      }
      window.addEventListener("keydown", playSound);

      const keys = document.querySelectorAll(".key");
      for (let index = 0; index < keys.length; index++) {
        keys[index].addEventListener("transitionend", stopSound);
      }

当我按住按钮时,过渡效果会永久添加到按钮上,并且按钮不会恢复正常。当我在过渡结束后立即删除课程时,为什么会发生这种情况。 代码:https://github.com/heysujal/drumkit2

2 个答案:

答案 0 :(得分:0)

我发现当 transitionend 事件被阻止触发时,该效果会永久添加(就像我在评论中所说的那样)。
要解决此问题,您只需在 setTimeout 函数中添加一个 playSound(),以在一定时间后移除该类。

function playSound(e) {
  const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);

  const pressedKey = document.querySelector(
    `.key[data-key="${e.keyCode}"]`
  );

  if (!audio) return;

  pressedKey.classList.add("playing");

  audio.currentTime = 0;
  audio.play();
  setTimeout(() => pressedKey.classList.remove("playing"), 150);
}  

fiddle 上试用。

答案 1 :(得分:0)

对于诸如 transitionbox-shadow 之类的昂贵属性,处理转换的方式似乎存在错误。我设法在 Chrome、Firefox 和 Safari 中重现了这种行为,但看起来 Chrome 总是这样做,而 Firefox 和 Safari 则更加随机。

一个简单的解决方法是将 transform 中的 if (e.propertyName !== "transform") return; 替换为更便宜的属性,例如 border-top-color

if (e.propertyName !== "border-top-color") return;

但我怀疑您是否想在应用中依赖 keydown 重复,因为您无法控制重复间隔。您可以考虑完全禁用重复声音:

function playSound(e) {
  if (e.repeat) return;
  // ...
}

或者,如果您想保持重复,我建议您为此实现一个自定义计时器,让您可以控制在下一次点击之前要等待的时间。