Last active
June 19, 2019 08:42
-
-
Save tundeiness/031f11e91ee2b4b9c79d2bb79d9fe7d1 to your computer and use it in GitHub Desktop.
Drum-Machine
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="root"></div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class App extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
childDisplay: "", | |
recorder: [], | |
data: [], | |
drumTime: null, | |
sounds: null, | |
recordTime: null | |
}; | |
this.handleDisplay = this.handleDisplay.bind(this); | |
this.onRecord = this.onRecord.bind(this); | |
this.drumEventTime = this.drumEventTime.bind(this); | |
this.recordSound = this.recordSound.bind(this); | |
} | |
handleDisplay(data) { | |
this.setState({ | |
childDisplay: data | |
}); | |
} | |
getData = refData => { | |
this.setState( | |
{ | |
data: refData | |
}, | |
() => this.state.data | |
); | |
}; | |
drumEventTime(keyTime) { | |
const drumTiming = this.state.drumTime; | |
this.setState( | |
{ | |
drumTime: keyTime | |
}, | |
() => this.state.drumTime | |
); | |
} | |
recordSound(clickData) { | |
this.setState( | |
{ | |
recorder: [...this.state.recorder, clickData] | |
}, | |
() => this.state.recorder | |
); | |
} | |
onReset = () => { | |
this.setState({ | |
recorder: [] | |
}); | |
}; | |
onRecord(recordStartTime) { | |
this.setState( | |
{ | |
recordTime: recordStartTime | |
}, | |
() => this.state.recordTime | |
); | |
} | |
getSoundFile = soundData => { | |
this.setState( | |
{ | |
sounds: soundData | |
}, | |
() => this.state.sounds | |
); | |
}; | |
togglePlay = () => { | |
const copyRecords = this.state.recorder; | |
const sounds = copyRecords.map((val, i) => { | |
return new Audio(val.link); | |
}) | |
copyRecords.map((arr, idx)=>{ | |
if (idx === 0) { | |
sounds[idx].play(); | |
}else{ | |
setTimeout(() => { | |
sounds[idx].play(); | |
}, arr.time - copyRecords[0].time); | |
} | |
}); | |
} | |
render() { | |
return ( | |
<div id="drum-machine"> | |
<Display | |
childDisplay={this.state.childDisplay} | |
displayRecord={this.onRecord} | |
reset={this.onReset} | |
onClickPlay={this.togglePlay} | |
soundData={this.state.sounds} | |
soundRecord={this.recordSound} | |
/> | |
<Drums | |
handleDisplay={this.handleDisplay} | |
handleRecord={this.onRecord} | |
getData={this.getData} | |
padEvent={this.drumEventTime} | |
getSoundFile={this.getSoundFile} | |
soundRecord={this.recordSound} | |
/> | |
</div> | |
); | |
} | |
} | |
class Display extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
showIcons: false, | |
defaultColor: "gray85" | |
}; | |
} | |
handleClickRecord = event => { | |
// reset recorder in App to empty | |
this.props.reset(); | |
let date = new Date(); | |
let recordStart = date.getTime(); | |
this.props.displayRecord(recordStart); | |
this.setState({ | |
showIcons: !this.state.showIcons | |
}); | |
}; | |
pressPlay = () => { | |
this.props.onClickPlay(); | |
if(this.props.soundData.length > 0){ | |
this.setState({ | |
defaultColor: "red" | |
}); | |
}else{ | |
this.setState({ | |
defaultColor: "Gray85" | |
}); | |
} | |
}; | |
render() { | |
return ( | |
<div id="dis-controls"> | |
<div id="display">{this.props.childDisplay}</div> | |
<div id="controls"> | |
<div id="play" style={{background: this.state.defaultColor}} onClick={this.pressPlay} > | |
<i class="fas fa-play" /> | |
</div> | |
<div id="record" onClick={this.handleClickRecord}> | |
<span className="fas fa-circle" /> | |
</div> | |
</div> | |
</div> | |
); | |
} | |
} | |
class Drums extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
soundFile: [ | |
{ | |
key: "Q", | |
url: "https://s3.amazonaws.com/freecodecamp/drums/Heater-1.mp3", | |
name: "Heater 1", | |
code: 81 | |
}, | |
{ | |
key: "W", | |
url: "https://s3.amazonaws.com/freecodecamp/drums/Kick_n_Hat.mp3", | |
name: "Kick n Hat", | |
code: 87 | |
}, | |
{ | |
key: "E", | |
url: "https://s3.amazonaws.com/freecodecamp/drums/Brk_Snr.mp3", | |
name: "Snare", | |
code: 69 | |
}, | |
{ | |
key: "A", | |
url: "https://s3.amazonaws.com/freecodecamp/drums/Heater-4_1.mp3", | |
name: "Heater 4", | |
code: 65 | |
}, | |
{ | |
key: "S", | |
url: "https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3", | |
name: "Clap", | |
code: 83 | |
}, | |
{ | |
key: "D", | |
url: "https://s3.amazonaws.com/freecodecamp/drums/Dsc_Oh.mp3", | |
name: "Open HH", | |
code: 68 | |
}, | |
{ | |
key: "Z", | |
url: "https://s3.amazonaws.com/freecodecamp/drums/punchy_kick_1.mp3", | |
name: "Punchy Kick", | |
code: 90 | |
}, | |
{ | |
key: "X", | |
url: "https://s3.amazonaws.com/freecodecamp/drums/RP4_KICK_1.mp3", | |
name: "Kick", | |
code: 88 | |
}, | |
{ | |
key: "C", | |
url: "https://s3.amazonaws.com/freecodecamp/drums/Cev_H2.mp3", | |
name: "Closed HH", | |
code: 67 | |
} | |
] | |
}; | |
this.myRef = []; | |
this.focusPad = this.focusPad.bind(this); | |
this.handleKeyPress = this.handleKeyPress.bind(this); | |
} | |
focusPad(event) { | |
let date = new Date(); | |
let keyTime = date.getTime(); | |
this.props.handleDisplay(event.currentTarget.id); | |
const datam = this.myRef; | |
const data = this.state.soundFile; | |
this.props.getData(datam); | |
// this.props.handleRecord(datam) | |
this.props.padEvent(keyTime); | |
this.props.getSoundFile(data); | |
datam.map((el, idx) => { | |
if (event.target.id == data[idx].name) { | |
const clickData = { | |
time: keyTime, | |
id: data[idx].key, | |
link: data[idx].url | |
}; | |
this.props.soundRecord(clickData); | |
return this.myRef[idx].play(); | |
} | |
}); | |
} | |
handleKeyPress(event) { | |
const refData = this.myRef; | |
const data = this.state.soundFile; | |
let date = new Date(); | |
let keyPressTime = date.getTime(); | |
refData.map((ele, indx) => { | |
if (event.keyCode == data[indx].code) { | |
const clickData = { | |
time: keyPressTime, | |
id: data[indx].key, | |
link: data[indx].url | |
}; | |
this.props.soundRecord(clickData); | |
this.props.handleDisplay(data[indx].name); | |
return this.myRef[indx].play(); | |
} | |
}); | |
} | |
componentDidMount() { | |
document.addEventListener("keydown", this.handleKeyPress, false); | |
} | |
componentWillUnmount() { | |
document.removeEventListener("keydown", this.handleKeyPress, false); | |
} | |
render() { | |
const soundData = this.state.soundFile; | |
return ( | |
<div id="drums"> | |
{soundData.map((index, droms) => { | |
return ( | |
<div | |
key={droms} | |
className="drum-pad" | |
id={index.name} | |
onClick={this.focusPad} | |
> | |
<p>{index.key}</p> | |
<audio | |
src={index.url} | |
type="audio/mpeg" | |
className="clip" | |
id={index.key} | |
ref={ref => (this.myRef[droms] = ref)} | |
/> | |
</div> | |
); | |
})} | |
</div> | |
); | |
} | |
} | |
ReactDOM.render(<App />, document.getElementById("root")); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.7.0/umd/react.production.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.1/umd/react-dom.production.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css"></script> | |
<script src="https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@import url('https://fonts.googleapis.com/css?family=Roboto:700|Press+Start+2P'); | |
*{ | |
box-sizing: border-box; | |
margin: 0; | |
padding: 0; | |
border: 0; | |
font-size: 100%; | |
font: inherit; | |
vertical-align: baseline; | |
} | |
#root{ | |
background-color: #FFDEE9; | |
background-image: linear-gradient(0deg, #FFDEE9 0%, #B5FFFC 100%); | |
height: 100vh; | |
overflow: hidden; | |
} | |
#drum-machine{ | |
border: 4px solid black; | |
border-radius: 3%; | |
width: 57%; | |
height: 65%; | |
margin: 8em auto; | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
} | |
#dis-controls{ | |
display: flex; | |
flex-direction: row; | |
width: 98%; | |
height: 25%; | |
margin: 5px 2px; | |
#display{ | |
flex: 1; | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
justify-content: center; | |
border: 1px solid rgba(0,0,255, 0.1); | |
border-radius: 1.5%; | |
height: 92%; | |
margin-top: 0.5%; | |
margin-left: 1%; | |
font-family: 'Press Start 2P', cursive; | |
background-color: rgba(0,0,255, 0.1); | |
#icons{ | |
display: flex; | |
flex-direction: row; | |
justify-content: space-around; | |
height: 22%; | |
margin-top: -40px; | |
margin-bottom: 32px; | |
margin-left: 100px; | |
#rectext{ | |
display: flex; | |
flex-direction: row; | |
font-size: 20%; | |
margin-top: 7px; | |
margin-left: 3px; | |
height: 8px; | |
width: 19px; | |
} | |
.rec{ | |
display: flex; | |
flex-direction: row; | |
font-size: 20%; | |
margin-top: 5px; | |
margin-left: 3px; | |
height: 8px; | |
width: 19px; | |
height: 8px; | |
width: 8px; | |
border-radius: 50%; | |
-webkit-animation: rec 0.8s ease-in-out infinite both; | |
animation: rec 0.8s ease-in-out infinite both; | |
@-webkit-keyframes rec { | |
0% { | |
-webkit-transform: scale(0.2); | |
transform: scale(0.2); | |
opacity: 0.8; | |
} | |
80% { | |
-webkit-transform: scale(1.2); | |
transform: scale(1.2); | |
opacity: 0; | |
} | |
100% { | |
-webkit-transform: scale(2.2); | |
transform: scale(2.2); | |
opacity: 0; | |
} | |
} | |
@keyframes rec { | |
0% { | |
-webkit-transform: scale(0.2); | |
transform: scale(0.2); | |
opacity: 0.8; | |
} | |
80% { | |
-webkit-transform: scale(1.2); | |
transform: scale(1.2); | |
opacity: 0; | |
} | |
100% { | |
-webkit-transform: scale(2.2); | |
transform: scale(2.2); | |
opacity: 0; | |
} | |
} | |
} | |
.play{ | |
display: flex; | |
flex-direction: row; | |
font-size: 20%; | |
margin-top: 5px; | |
margin-left: 3px; | |
height: 8px; | |
width: 19px; | |
} | |
} | |
} | |
#controls{ | |
display: flex; | |
flex-direction: row; | |
width: 30%; | |
margin-left: 1.3%; | |
#play{ | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
justify-content: center; | |
border: 1px solid gray; | |
width: 45%; | |
margin-left: 2%; | |
margin-right: 1%; | |
margin-top: 2%; | |
border-radius: 10%; | |
height: 92%; | |
background-color: #d9d9d9; | |
background-image: linear-gradient(315deg, #d9d9d9 0%, #f6f2f2 74%); | |
-webkit-box-shadow: 3px 4px 13px -4px rgba(0,0,0,0.7); | |
-moz-box-shadow: 3px 4px 13px -4px rgba(0,0,0,0.7); | |
box-shadow: 3px 4px 13px -4px rgba(0,0,0,0.7); | |
} | |
.switch{ | |
background-color: red; | |
} | |
.normal{ | |
background-color: gray85; | |
} | |
#record{ | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
justify-content: center; | |
border: 1px solid gray; | |
width: 45%; | |
margin-left: 2%; | |
margin-top: 2%; | |
border-radius: 10%; | |
height: 92%; | |
background-color: #d9d9d9; | |
background-image: linear-gradient(315deg, #d9d9d9 0%, #f6f2f2 74%); | |
-webkit-box-shadow: 3px 4px 13px -4px rgba(0,0,0,0.7); | |
-moz-box-shadow: 3px 4px 13px -4px rgba(0,0,0,0.7); | |
box-shadow: 3px 4px 13px -4px rgba(0,0,0,0.7); | |
.fa-circle{ | |
color: red; | |
} | |
} | |
} | |
} | |
#drums{ | |
display: flex; | |
flex-wrap: wrap; | |
flex-direction: row; | |
justify-content: center; | |
width: 98%; | |
height: 70%; | |
#drums > .drum-pad{ | |
} | |
.drum-pad{ | |
display: flex; | |
flex-direction: column; | |
justify-content: center; | |
align-items: center; | |
border: 1px solid red; | |
width: 30.33%; | |
margin-right: 1%; | |
margin-left: 1%; | |
margin-top: 0.7%; | |
margin-bottom: 0.7%; | |
border-radius: 4%; | |
background-color: #d9d9d9; | |
background-image: linear-gradient(315deg, #d9d9d9 0%, #f6f2f2 74%); | |
font-family: 'Roboto', sans-serif; | |
-webkit-box-shadow: 3px 4px 13px -4px rgba(0,0,0,0.7); | |
-moz-box-shadow: 3px 4px 13px -4px rgba(0,0,0,0.7); | |
box-shadow: 3px 4px 13px -4px rgba(0,0,0,0.7); | |
} | |
.drum-pad:hover{ | |
border: 2px solid gray; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment