首页 > 解决方案 > 尝试在单击时播放音频文件时无法读取未定义的属性“keyCode”

问题描述

尝试将 onclick 事件添加到具有现有功能的 div 水平,该功能在按下某个键时播放声音

我尝试将 playSound() 函数添加到我的 div 中的 onclick 中,但不断收到未定义的错误,按键仍然可以正常工作。我还尝试将可以播放声音的功能分离出来,但是还有一个应该添加的小动画类,并且在尝试时遇到了相同的未定义错误

    <div data-key="65" class="key" onclick="playSound()">
      <kbd>A</kbd>
      <span class="sound">clap</span>
    </div>  

  <audio data-key="65" src="sounds/clap.wav"></audio>
  <audio data-key="83" src="sounds/hihat.wav"></audio>
  <audio data-key="68" src="sounds/kick.wav"></audio>
  <audio data-key="70" src="sounds/openhat.wav"></audio>
  <audio data-key="71" src="sounds/boom.wav"></audio>
  <audio data-key="72" src="sounds/ride.wav"></audio>
  <audio data-key="74" src="sounds/snare.wav"></audio>
  <audio data-key="75" src="sounds/tom.wav"></audio>
  <audio data-key="76" src="sounds/tink.wav"></audio>

  <script>

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

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

    const keys = document.querySelectorAll('.key');
    keys.forEach(key => key.addEventListener('transitionend', removeTransition));
    window.addEventListener('keydown', playSound);
  </script>

我希望能够同时按下一个键并单击/触摸屏幕上的字母以在动画中播放声音,目前它只能通过按键完全运行

标签: javascriptaudioonclick

解决方案


您收到“无法读取未定义的属性 'keyCode'”,因为您没有playSoundonclick事件处理程序中将任何参数传递给您的函数,并且预计会收到一个引用键盘事件的参数。

一种更有效的方法应该是使playSound函数更通用,接收 keyCode 本身而不是键盘事件。这样您就可以在代码中的其他位置调用它而不会出现其他问题。

您还可以制作一个特定的函数来在单击时播放声音,您可以将元素作为参数传递给该函数。

这将如下所示:

<div data-key="65" class="key" onclick="clickPlay(this)">
    <kbd>A</kbd>
    <span class="sound">clap</span>
</div>

<audio data-key="65" src="sounds/clap.wav"></audio>
<audio data-key="83" src="sounds/hihat.wav"></audio>
<audio data-key="68" src="sounds/kick.wav"></audio>
<audio data-key="70" src="sounds/openhat.wav"></audio>
<audio data-key="71" src="sounds/boom.wav"></audio>
<audio data-key="72" src="sounds/ride.wav"></audio>
<audio data-key="74" src="sounds/snare.wav"></audio>
<audio data-key="75" src="sounds/tom.wav"></audio>
<audio data-key="76" src="sounds/tink.wav"></audio>
// Receive the keyCode directly instead of the event
function playSound(key) {
    const audio = document.querySelector(`audio[data-key="${key}"]`);
    const keyEl = document.querySelector(`.key[data-key="${key}"]`);

    if (!audio) return;
    audio.currentTime = 0;
    audio.play();

    if (!keyEl) return;
    keyEl.classList.add('playing');
}

// New function to be executed when clicking
function clickPlay(el) {
    const key = el.attributes['data-key'].value; // Getting the keyCode from dom element
    playSound(key);
}

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

const keys = document.querySelectorAll('.key');
keys.forEach(key => key.addEventListener('transitionend', removeTransition));
window.addEventListener('keydown', e => {
    const key = e.keyCode; // Getting the keyCode from keyboard
    playSound(key);
});

推荐阅读