Piano Please
body {
margin: 0;
}
html,
body,
.wrapper {
height: 100%;
}
.wrapper {
display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: center;
}
.piano {
background-color: #ccc;
padding: 20px;
height: 300px;
width: 785px;
border-radius: 20px;
transform: scale(1);
}
.key {
position: relative;
float: left;
margin-top: 50px;
border-radius: 0 0 0.5rem 0.5rem;
}
.key.key--black {
background-image: linear-gradient(#1a1a1a 100%, #444 0%);
width: 30px;
height: 150px;
left: 15px;
z-index: 2;
margin-left: -30px;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.4);
}
.key.key--black:active {
background-image: linear-gradient(#1a1a1a 0%, #444 100%);
}
.key.key--white {
background-image: linear-gradient(#f1f1f1 100%, #ddd 0%);
width: 50px;
height: 250px;
border: 1px solid #ccc;
}
.key.key--white:last-child {
border-right: 0;
}
.key.key--white:active {
background-image: linear-gradient(#f1f1f1 0%, #ddd 100%);
}
@media screen and (max-width: 900px) {
.piano {
transform: scale(0.8);
}
}
@media screen and (max-width: 840px) {
.piano {
transform: scale(0.6);
}
}
// ===== DATA AND GLOBALS ===== //
const audioCtx = new AudioContext();
const frequencies = {
'c0': 16.35,
'cis0': 17.32,
'd0': 18.35,
'dis0': 19.45,
'e0': 20.60,
'f0': 21.83,
'fis0': 23.12,
'g0': 24.50,
'gis0': 25.96,
'a0': 27.50,
'ais0': 29.14,
'b0': 30.87,
'c1': 32.70,
'cis1': 34.65,
'd1': 36.71,
'dis1': 38.89,
'e1': 41.20,
'f1': 43.65,
'fis1': 46.25,
'g1': 49.00,
'gis1': 51.91,
'a1': 55.00,
'ais1': 58.27,
'b1': 61.74,
'c2': 65.41,
'cis2': 69.30,
'd2': 73.42,
'dis2': 77.78,
'e2': 82.41,
'f2': 87.31,
'fis2': 92.50,
'g2': 98.00,
'gis2': 103.83,
'a2': 110.00,
'ais2': 116.54,
'b2': 123.47,
'c3': 130.81,
'cis3': 138.59,
'd3': 146.83,
'dis3': 155.56,
'e3': 164.81,
'f3': 174.61,
'fis3': 185.00,
'g3': 196.00,
'gis3': 207.65,
'a3': 220.00,
'ais3': 233.08,
'b3': 246.94,
'c4': 261.63,
'cis4': 277.18,
'd4': 293.66,
'dis4': 311.13,
'e4': 329.63,
'f4': 349.23,
'fis4': 369.99,
'g4': 392.00,
'gis4': 415.30,
'a4': 440.00,
'ais4': 466.16,
'b4': 493.88, // continue from here
'c5': 65.41,
'cis5': 69.30,
'd5': 73.42,
'dis5': 77.78,
'e5': 82.41,
'f5': 87.31,
'fis5': 92.50,
'g5': 98.00,
'gis5': 103.83,
'a5': 110.00,
'ais5': 116.54,
'b5': 123.47,
'c6': 65.41,
'cis6': 69.30,
'd6': 73.42,
'dis6': 77.78,
'e6': 82.41,
'f6': 87.31,
'fis6': 92.50,
'g6': 98.00,
'gis6': 103.83,
'a6': 110.00,
'ais6': 116.54,
'b6': 123.47,
'c7': 65.41,
'cis7': 69.30,
'd7': 73.42,
'dis7': 77.78,
'e7': 82.41,
'f7': 87.31,
'fis7': 92.50,
'g7': 98.00,
'gis7': 103.83,
'a7': 110.00,
'ais7': 116.54,
'b7': 123.47,
'c8': 65.41,
'cis8': 69.30,
'd8': 73.42,
'dis8': 77.78,
'e8': 82.41,
'f8': 87.31,
'fis8': 92.50,
'g8': 98.00,
'gis8': 103.83,
'a8': 110.00,
'ais8': 116.54,
'b8': 123.47
};
// ===== ELEMENTS AND EVENTLISTENERS ===== //
const keys = Array.from(document.querySelectorAll('.key'));
keys.forEach(k => k.addEventListener('click', playSound))
// ===== LOGIC ===== //
function playSound({ target }) {
const playFrequency =
frequencies[target.getAttribute('data-tone')];
const oscillator = audioCtx.createOscillator();
const gain = audioCtx.createGain();
oscillator.type = 'sine';
oscillator.frequency.value = playFrequency;
oscillator.connect(gain);
gain.connect(audioCtx.destination);
oscillator.start(0);
gain.gain.exponentialRampToValueAtTime(
0.000001,
audioCtx.currentTime + 1
);
}
<div class="wrapper">
<div class="controls">
<span>Octaves</span>
<input type="text" name="octave-left">
and
<input type="text" name="octave-right">
</div>
<div class="piano">
<div class="key key--white" data-tone="c3"></div>
<div class="key key--black" data-tone="cis3"></div>
<div class="key key--white" data-tone="d3"></div>
<div class="key key--black" data-tone="dis3"></div>
<div class="key key--white" data-tone="e3"></div>
<div class="key key--white" data-tone="f3"></div>
<div class="key key--black" data-tone="fis3"></div>
<div class="key key--white" data-tone="g3"></div>
<div class="key key--black" data-tone="gis3"></div>
<div class="key key--white" data-tone="a3"></div>
<div class="key key--black" data-tone="ais3"></div>
<div class="key key--white" data-tone="b3"></div>
<div class="key key--white" data-tone="c4"></div>
<div class="key key--black" data-tone="cis4"></div>
<div class="key key--white" data-tone="d4"></div>
<div class="key key--black" data-tone="dis4"></div>
<div class="key key--white" data-tone="e4"></div>
<div class="key key--white" data-tone="f4"></div>
<div class="key key--black" data-tone="fis4"></div>
<div class="key key--white" data-tone="g4"></div>
<div class="key key--black" data-tone="gis4"></div>
<div class="key key--white" data-tone="a4"></div>
<div class="key key--black" data-tone="ais4"></div>
<div class="key key--white" data-tone="b4"></div>
<div class="key key--white" data-tone="c5"></div>
</div>
</div>