Skip to content

Instantly share code, notes, and snippets.

@savepong
Created February 18, 2021 17:38
Show Gist options
  • Save savepong/a9e05d6d71c05bfc4dda0d6d876543ad to your computer and use it in GitHub Desktop.
Save savepong/a9e05d6d71c05bfc4dda0d6d876543ad to your computer and use it in GitHub Desktop.
Drum Machine
<script src="https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js"></script>
<div id="app"></div>
const sounds = [
{
keyCode: 81,
keyTrigger: 'Q',
id: 'Heater-1',
url: 'https://s3.amazonaws.com/freecodecamp/drums/Heater-1.mp3'
},
{
keyCode: 87,
keyTrigger: 'W',
id: 'Heater-2',
url: 'https://s3.amazonaws.com/freecodecamp/drums/Heater-2.mp3'
},
{
keyCode: 69,
keyTrigger: 'E',
id: 'Heater-3',
url: 'https://s3.amazonaws.com/freecodecamp/drums/Heater-3.mp3'
},
{
keyCode: 65,
keyTrigger: 'A',
id: 'Heater-4',
url: 'https://s3.amazonaws.com/freecodecamp/drums/Heater-4_1.mp3'
},
{
keyCode: 83,
keyTrigger: 'S',
id: 'Clap',
url: 'https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3'
},
{
keyCode: 68,
keyTrigger: 'D',
id: 'Open-HH',
url: 'https://s3.amazonaws.com/freecodecamp/drums/Dsc_Oh.mp3'
},
{
keyCode: 90,
keyTrigger: 'Z',
id: "Kick-n'-Hat",
url: 'https://s3.amazonaws.com/freecodecamp/drums/Kick_n_Hat.mp3'
},
{
keyCode: 88,
keyTrigger: 'X',
id: 'Kick',
url: 'https://s3.amazonaws.com/freecodecamp/drums/RP4_KICK_1.mp3'
},
{
keyCode: 67,
keyTrigger: 'C',
id: 'Closed-HH',
url: 'https://s3.amazonaws.com/freecodecamp/drums/Cev_H2.mp3'
}
];
const activeStyle = {
backgroundColor: '#f5f6f7',
};
const inactiveStyle = {
backgroundColor: '#91919c',
};
class DrumPad extends React.Component {
constructor(props) {
super(props);
this.state = {
padStyle: inactiveStyle
};
this.playSound = this.playSound.bind(this);
this.handleKeyPress = this.handleKeyPress.bind(this);
this.activatePad = this.activatePad.bind(this);
}
componentDidMount() {
document.addEventListener('keydown', this.handleKeyPress);
}
componentWillUnmount() {
document.removeEventListener('keydown', this.handleKeyPress);
}
handleKeyPress(e) {
if (e.keyCode === this.props.keyCode) {
this.playSound();
}
}
activatePad() {
if (this.state.padStyle.backgroundColor === '#f5f6f7') {
this.setState({
padStyle: inactiveStyle
});
} else {
this.setState({
padStyle: activeStyle
});
}
}
playSound() {
const sound = document.getElementById(this.props.keyTrigger);
sound.currentTime = 0;
sound.play();
this.activatePad();
setTimeout(() => this.activatePad(), 200);
this.props.updateDisplay(this.props.clipId.replace(/-/g, ' '));
}
render() {
return (
<div
className='drum-pad'
id={this.props.clipId}
onClick={this.playSound}
style={this.state.padStyle}
>
<audio
className='clip'
id={this.props.keyTrigger}
src={this.props.clip}
/>
{this.props.keyTrigger}
</div>
);
}
}
class PadBank extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className='pad-bank'>
{this.props.currentPadBank.map((drumObj, i, padBankArr) => {
return (
<DrumPad
clip={padBankArr[i].url}
clipId={padBankArr[i].id}
keyCode={padBankArr[i].keyCode}
keyTrigger={padBankArr[i].keyTrigger}
updateDisplay={this.props.updateDisplay}
/>
);
})}
</div>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
display: String.fromCharCode(160),
currentPadBank: sounds,
currentPadBankId: 'Heater Kit',
sliderVal: 1
};
this.displayClipName = this.displayClipName.bind(this);
this.clearDisplay = this.clearDisplay.bind(this);
}
displayClipName(name) {
this.setState({
display: name
});
}
clearDisplay() {
this.setState({
display: String.fromCharCode(160)
});
}
render() {
{
const clips = [].slice.call(document.getElementsByClassName('clip'));
clips.forEach(sound => {
sound.volume = this.state.sliderVal;
});
}
return (
<div className='container' id='drum-machine'>
<h1 id='display'>{this.state.display}</h1>
<PadBank
clipVolume={this.state.sliderVal}
currentPadBank={this.state.currentPadBank}
updateDisplay={this.displayClipName}
/>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.min.js"></script>
html, body {
padding: 0px;
margin: 0px;
font-family: sans-serif;
background-color: #1b1b32;
user-select: none;
}
#app {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
position: relative;
width: 600px;
/* height: 100%; */
text-align: center;
margin: 0 auto;
}
.drum-pad {
position: relative;
float: left;
width: 33%;
height: 100px;
margin: 1px;
padding-top: 35px;
box-sizing: border-box;
cursor: pointer;
color: #1b1b32;
font-size: 30px;
font-weight: 100;
}
#display {
color: white;
width: 200px;
margin: 15px auto;
padding: 15px;
box-sizing: border-box;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment