我正在学习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问题上,该按钮停留了一段时间。任何帮助表示赞赏。
答案 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'));