Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d3fbaa3

Browse files
Merge pull request #3 from palashmon/play-notes-loop
Added some auto drum notes
2 parents 1e9ad8c + ed3fdad commit d3fbaa3

File tree

4 files changed

+170
-53
lines changed

4 files changed

+170
-53
lines changed
Lines changed: 136 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
<!DOCTYPE html>
22
<html lang="en">
3+
34
<head>
45
<meta charset="UTF-8">
56
<title>JS Drum Kit</title>
67
<link rel="stylesheet" href="style.css">
78
</head>
9+
810
<body>
911

1012

@@ -47,51 +49,148 @@
4749
</div>
4850
</div>
4951

52+
<input type="button" value="Start Audio" id="playAudioButton"></input>
53+
5054
<audio data-key="65" src="sounds/clap.wav"></audio>
51-
<audio data-key="83" src="sounds/hihat.wav"></audio>
55+
<audio data-key="83" src="sounds/closedhat.wav"></audio>
5256
<audio data-key="68" src="sounds/kick.wav"></audio>
5357
<audio data-key="70" src="sounds/openhat.wav"></audio>
5458
<audio data-key="71" src="sounds/boom.wav"></audio>
5559
<audio data-key="72" src="sounds/ride.wav"></audio>
5660
<audio data-key="74" src="sounds/snare.wav"></audio>
5761
<audio data-key="75" src="sounds/tom.wav"></audio>
58-
<audio data-key="76" src="sounds/tink.wav"></audio>
59-
60-
<script>
61-
62-
/************************************************************************************************
63-
GOAL: When a user opens this page and presses a key that corresponds with
64-
one of our div elements, we should play the audio clip associated with
65-
the keypress, add a class to the specific element that matches with the keypress,
66-
and then remove that class in order to reset the element to it's original state.
67-
**************************************************************************************************/
68-
69-
function removeTransition(e) {
70-
// Skip if it's not a transform event
71-
if (e.propertyName !== 'transform') return;
72-
e.target.classList.remove('playing');
73-
}
74-
75-
function playSound(e) {
76-
const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
77-
const key = document.querySelector(`div[data-key="${e.keyCode}"]`);
78-
79-
// Stop function from running if key pressed doesn't match up with our elements data-key value
80-
if (!audio) return;
81-
key.classList.add('playing');
82-
83-
// Play sound clip from start every time a corresponding key is pressed
84-
audio.currentTime = 0;
85-
audio.play();
86-
}
87-
88-
// Find all elements in the document with a class 'key'
89-
const keys = Array.from(document.querySelectorAll('.key'));
90-
keys.forEach(key => key.addEventListener('transitionend', removeTransition));
91-
window.addEventListener('keydown', playSound);
92-
93-
</script>
62+
<audio data-key="76" src="sounds/tinkbell.wav"></audio>
63+
64+
<script>
65+
66+
/************************************************************************************************
67+
GOAL: When a user opens this page and presses a key that corresponds with
68+
one of our div elements, we should play the audio clip associated with
69+
the keypress, add a class to the specific element that matches with the keypress,
70+
and then remove that class in order to reset the element to it's original state.
71+
**************************************************************************************************/
72+
73+
function removeTransition(e) {
74+
// Skip if it's not a transform event
75+
if (e.propertyName !== 'transform') return;
76+
e.target.classList.remove('playing');
77+
}
78+
79+
function playSound(e) {
80+
81+
// If space key is pressed then start the auto drum notes
82+
if (e.code === 'Space') {
83+
play();
84+
return;
85+
}
86+
87+
const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
88+
const key = document.querySelector(`div[data-key="${e.keyCode}"]`);
89+
90+
// Stop function from running if key pressed doesn't match up with our elements data-key value
91+
if (!audio) return;
92+
key.classList.add('playing');
93+
94+
// Play sound clip from start every time a corresponding key is pressed
95+
audio.currentTime = 0;
96+
audio.play();
97+
}
98+
99+
// Find all elements in the document with a class 'key'
100+
const keys = Array.from(document.querySelectorAll('.key'));
101+
keys.forEach(key => key.addEventListener('transitionend', removeTransition));
102+
window.addEventListener('keydown', playSound);
103+
104+
105+
/************************************************************************************************
106+
Play some auto drum notes
107+
************************************************************************************************/
108+
let playing = false;
109+
let interval;
110+
const totalSteps = 16;
111+
let currentStep = 1;
112+
let fullSteps = Array.from({ length: 16 }, () => []);
113+
const kick = 68;
114+
const hihat = 83;
115+
const snare = 74;
116+
const tink = 76;
117+
let bpm = 12; // increase or decrease this 12 param to see change in beats per minute
118+
let count = 0;
119+
120+
// Add the click event listener to our play button
121+
const playAudioButton = document.querySelector('#playAudioButton');
122+
playAudioButton.addEventListener('click', play);
123+
124+
// Toggle the play button and start/stop the audio based on current state
125+
function play(e) {
126+
playAudioButton.value = playing ? 'Start Audio' : 'Stop Audio';
127+
if (playing) {
128+
stopAudio();
129+
} else {
130+
startAudio();
131+
}
132+
playing = !playing;
133+
}
134+
135+
// Play the instrument that is set for current step
136+
function playStep(step) {
137+
return Array.from(fullSteps[step]).map((keyCode) => playSound({ keyCode }));
138+
}
139+
140+
// Start the audio, if play button is clicked
141+
function startAudio() {
142+
interval = setInterval(() => {
143+
144+
// Add hihat after 2nd round
145+
if (++count === 32) {
146+
createNotes(hihat, [1, 3, 5, 7, 9, 11, 13, 15]);
147+
}
148+
149+
// Add tink after 4th round
150+
if (count === 32 * 2) {
151+
createNotes(tink, [2, 4, 7, 12]);
152+
}
153+
if (count === 32 * 4) {
154+
createNotes(tink, [3, 5, 8, 13]);
155+
}
156+
157+
playStep(currentStep - 1);
158+
currentStep = (currentStep < totalSteps) ? currentStep + 1 : 1;
159+
if (!playing) stopAudio();
160+
}, ~~(1500 / bpm));
161+
}
162+
163+
// Stop the audio, if stop button is clicked
164+
function stopAudio() {
165+
clearInterval(interval);
166+
currentStep = 1;
167+
count = 0;
168+
fullSteps = Array.from({ length: 16 }, () => []);
169+
createFullNotes();
170+
keys.forEach(key => key.classList.remove('playing'));
171+
}
172+
173+
// Create setup for what instrument needs to be played at what step
174+
function createNotes(instrument, steps) {
175+
return Array.from(steps).map((step) => {
176+
if (!Array.isArray(fullSteps[step - 1])) {
177+
fullSteps[step - 1] = [];
178+
}
179+
fullSteps[step - 1].push(instrument)
180+
});
181+
}
182+
183+
// Create all the notes needed to play the initial audio
184+
function createFullNotes() {
185+
createNotes(kick, [1, 4, 7, 11]);
186+
createNotes(snare, [5, 13]);
187+
}
188+
189+
// Initialize the initial audio notes
190+
createFullNotes();
191+
</script>
94192

95193

96194
</body>
195+
97196
</html>
Binary file not shown.
Binary file not shown.

‎Challenges/Day 01 - JavaScript Drum Kit/style.css

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,38 @@ html {
44
background-size: cover;
55
}
66

7-
body,html {
7+
body,
8+
html {
89
margin: 0;
910
padding: 0;
1011
font-family: sans-serif;
1112
}
1213

1314
.keys {
14-
display:flex;
15-
flex:1;
16-
min-height:100vh;
15+
display:flex;
16+
flex:1;
17+
min-height:100vh;
1718
align-items: center;
1819
justify-content: center;
1920
}
2021

2122
.key {
22-
border:4px solid black;
23-
border-radius:5px;
24-
margin:1rem;
23+
border:4px solid black;
24+
border-radius:5px;
25+
margin:1rem;
2526
font-size: 1.5rem;
26-
padding:1rem .5rem;
27-
transition:all .07s;
28-
width:100px;
27+
padding:1rem 0.5rem;
28+
transition:all 0.07s;
29+
width:100px;
2930
text-align: center;
30-
color:white;
31-
background:rgba(0,0,0,0.4);
32-
text-shadow:0 0 5px black;
31+
color:white;
32+
background:rgba(0,0,0,0.4);
33+
text-shadow:0 0 5px black;
3334
}
3435

3536
.playing {
36-
transform:scale(1.1);
37-
border-color:#ffc600;
37+
transform:scale(1.1);
38+
border-color:#ffc600;
3839
box-shadow: 0 0 10px #ffc600;
3940
}
4041

@@ -47,5 +48,22 @@ kbd {
4748
font-size: 1.2rem;
4849
text-transform: uppercase;
4950
letter-spacing: 1px;
50-
color:#ffc600;
51+
color: #ffc600;
52+
}
53+
54+
input[type='button'] {
55+
position: absolute;
56+
margin-left: -50px;
57+
left: 45%;
58+
bottom: 20%;
59+
border: 4px solid black;
60+
border-radius: 5px;
61+
margin: 1rem;
62+
font-size: 2.5rem;
63+
padding: 1rem 1.5rem;
64+
transition: all 0.07s;
65+
text-align: center;
66+
color: white;
67+
background: rgba(0, 0, 0, 0.4);
68+
text-shadow: 0 0 5px black;
5169
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /