反应触发按钮声音onKeyPress问题

时间:2018-08-28 03:15:46

标签: reactjs onclick event-handling keypress onkeypress

我正在学习React并致力于构建drum machine。我在使用onKeyPress触发按钮单击时触发声音时遇到问题。用鼠标单击时,按钮和声音工作正常,但是要使它们在键盘上按下即可工作,首先必须用鼠标单击该按钮。

似乎您单击一个按钮之后,该按钮一直保持焦点,直到用鼠标单击另一个按钮为止。

如何使用onKeyPress来触发带有按键的按钮? onKeyPress不是处理类似问题的正确方法吗?

看来这是与单击时关注的按钮有关的问题。

代码如下:

我有一个鼓显示组件,其中每个按钮/ div如下所示:

    <DrumPad
      id='Q'
      soundName='Heater 1'
      sound="https://s3.amazonaws.com/freecodecamp/drums/Heater-1.mp3"
      buttonClicked={props.buttonClicked}
      name={props.name}
      handleClick={props.handleClick}
      onKeyPress={props.onKeyPress}
    />

然后在另一个组件中,我有一个鼓垫组件,用于设置每个按钮及其功能:

import React, { Component } from 'react';


const DrumPad = (props) => {
  return (
    <div className="drum-pad"
      onClick={() => props.handleClick(props.id, props.soundName)}
      onKeyPress={() => props.handleClick(props.id, props.soundName)}
      tabIndex="0">

      <audio className="clip" id={props.id}>
        <source src={props.sound} type="audio/mp3" />
      </audio>
      <span>{props.id}</span>

    </div>
  );
}


export default DrumPad;

我的App.js主要组件很简单,它由本地状态和一个handleClick函数组成,用于处理按钮单击:

import React, { Component } from 'react';
import './App.css';
import DrumDisplay from './DrumContainer';
import MySlider from './Slider.js';
import handle from './Slider.js';
import Slider, { Range } from 'rc-slider';
import 'rc-slider/assets/index.css';
import 'rc-tooltip/assets/bootstrap.css';
import Tooltip from 'rc-tooltip';

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      buttonClicked: '',
      name: ''
    }
  }

  handleClick = (e, name) => {
    this.setState({ buttonClicked: e })
    this.setState({ name: name})

    const sound = document.getElementById(e);
    sound.volume = 1;
    sound.play();

  }


  render() {
    return (
      <DrumDisplay
        buttonClicked={this.state.buttonClicked}
        name={this.state.name}
        handleClick={this.handleClick}
        onKeyPress={this.handleClick}
      />
    );
  }
}

export default App;

在KeyPress问题上,该按钮停留了一段时间。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:0)

参加聚会为时已晚,但开始学习 html/css/javascript/react,因此以防万一它对其他人有帮助,这里是基于此代码并进行了一些修改的解决方案。

我在没有任何参数的情况下在 div 上调用了 onKeyPress,仅使用事件在主应用程序上对其进行了描述,并添加了 ComponentDidMount() 和 ComponentWillUnMount() 来处理事件侦听器。

它可以工作并通过了测试。唯一的挑战仍然是,您必须先单击按钮才能使按键起作用....... 仍在学习中,将来可能会解决这个问题。否则非常欢迎建议。

https://codepen.io/Mz12/pen/qBrwwXd

import React from "https://cdn.skypack.dev/react"
import ReactDOM from "https://cdn.skypack.dev/react-dom"

const descriptionStyle={
  position: 'absolute',
  width: '400px',
  height: '25px',
  top: '12.5%',
  left: '50%',
  margin: '-25px 0 0 -25px',
  textAlign: 'center'
}

const styles = {
  border: '1px solid black',
  position: 'absolute',
  width: '400px',
  height: '200px',
  top: '50%',
  left: '50%',
  margin: '-25px 0 0 -25px',
  backgroundColor: '#E6E6FA',
  display: 'grid',
  gridTemplateColumns: 'auto auto auto',
  gridGap: '50px'
};

const displayStyle = {
  border: '1px solid black',
  position: 'absolute',
  top: '50%',
  width: '400px',
  height: '50px',
  top: '35%',
  left: '50%',
  margin: '-25px 0 0 -25px',
  backgroundColor: '#E6E6FA',
  textAlign: 'center',
  fontSize: '25px',
};

const buttonStyle ={
  textAlign: 'center',
  fontSize: '25px',
  fontWeight: 'bold'
};

const developer={
  position: 'absolute',
  width: '400px',
  height: '25px',
  top: '80%',
  left: '50%',
  margin: '-25px 0 0 -25px',
  textAlign: 'right'
}

class DrumMachine extends React.Component{
  constructor(props){
    super(props);
    
    this.state={
      display:''
    };
    
  this.drumItemClick = this.drumItemClick.bind(this);
  this.drumItemPress = this.drumItemPress.bind(this);
    
  };

drumItemClick = (event, text) => {
      document.getElementById(event).play();
      this.setState((state) => {
      return {display: text};
    });
      
    };
  
  drumItemPress = (event) => {
    const key = event.key.toUpperCase()
    if('QWEASDZXC'.includes(key)){
      document.getElementById(key).play();
    };
      
  };
  
  ComponentDidMount(){
    document.addEventListener("keydown", this.drumItemPress)
  };
  
  ComponentWillUnMount(){
    document.removeEventListener("keydown", this.drumItemPress)
  };


render(){

return(
    <div id="drum-machine">
    <div style={descriptionStyle}>
      <h1>Drum Machine</h1>
      <p>Click or Press Keys to Play!</p>
    </div>
    <div id="display" style={displayStyle}>
      {this.state.display}
    </div>
    <div>
      < Heaters 
        drumItemClick={this.drumItemClick}
        drumItemPress={this.drumItemPress}
        />
    </div>
    <div style={developer}>by Mz.</div>
  </div>
);


 };
};

const Heaters = (props) => {



const drumItems=[
 
  {
   buttonId: "Heater1",
   buttonClass: 'drum-pad',
   buttonText: 'Q',
   audioId: "Q",
   audioSound: "https://s3.amazonaws.com/freecodecamp/drums/Heater-1.mp3",
   audioClass: 'clip',
  },
  
   {
   buttonId: "Heater2",
   buttonClass: 'drum-pad',
   buttonText: 'W',
   audioId: "W",
   audioSound: "https://s3.amazonaws.com/freecodecamp/drums/Heater-2.mp3",
   audioClass: 'clip',
  },
  
   {
   buttonId: "Heater3",
   buttonClass: 'drum-pad',
   buttonText: 'E',
   audioId: "E",
   audioSound: "https://s3.amazonaws.com/freecodecamp/drums/Heater-3.mp3",
   audioClass: 'clip',
  },
  
   {
   buttonId: "Heater4",
   buttonClass: 'drum-pad',
   buttonText: 'A',
   audioId: "A",
   audioSound: "https://s3.amazonaws.com/freecodecamp/drums/Heater-4_1.mp3",
   audioClass: 'clip',
  },
  
   {
   buttonId: "clap",
   buttonClass: 'drum-pad',
   buttonText: 'S',
   audioId: "S",
   audioSound: "https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3",
   audioClass: 'clip',
  },
  
   {
   buttonId: "OpenHH",
   buttonClass: 'drum-pad',
   buttonText: 'D',
   audioId: "D",
   audioSound: "https://s3.amazonaws.com/freecodecamp/drums/Dsc_Oh.mp3",
   audioClass: 'clip',
  },
  
   {
   buttonId: "KicknHat",
   buttonClass: 'drum-pad',
   buttonText: 'Z',
   audioId: "Z",
   audioSound: "https://s3.amazonaws.com/freecodecamp/drums/Kick_n_Hat.mp3",
   audioClass: 'clip',
  },
  
   {
   buttonId: "Kick",
   buttonClass: 'drum-pad',
   buttonText: 'X',
   audioId: "X",
   audioSound: "https://s3.amazonaws.com/freecodecamp/drums/RP4_KICK_1.mp3",
   audioClass: 'clip',
  },
  
   {
   buttonId: "ClosedHH",
   buttonClass: 'drum-pad',
   buttonText: 'C',
   audioId: "C",
   audioSound: "https://s3.amazonaws.com/freecodecamp/drums/Cev_H2.mp3",
   audioClass: 'clip',
  },
  
];



return(
    <div style={styles}>
           {
        drumItems.map((drumItem) => 
            (
              <button 
              id={drumItem.buttonId} class={drumItem.buttonClass}
                onClick={ () => props.drumItemClick(drumItem.audioId, drumItem.buttonId) } onKeyDown={props.drumItemPress} style={buttonStyle}>
            {drumItem.buttonText}
            <audio id={drumItem.audioId} src={drumItem.audioSound} class={drumItem.audioClass}></audio>
            </button>
            )
              )
                }
      
          </div>
      );
    };
    
    
    ReactDOM.render(<DrumMachine />, document.getElementById('root'));