Playable Piano Keyboard with Demos
How do I make an playable piano keyboard with demos?
Playable piano/keyboard using HTML audio API. Includes demos of No Suprises, Life on Mars, Für Elise and The Entertainer.. What is a playable piano keyboard with demos? How do you make a playable piano keyboard with demos? This script and codes were developed by Adam on 28 November 2022, Monday.
Playable Piano Keyboard with Demos - Script Codes HTML Codes
<!DOCTYPE html>
<html >
<head> <meta charset="UTF-8"> <title>Playable Piano Keyboard with Demos</title> <link href="https://fonts.googleapis.com/css?family=Condiment" rel="stylesheet"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css"> <link rel="stylesheet" href="css/style.css">
</head>
<body> <div class="wrap"> <!--Controls--> <div class="controls-container"> <div class="speakers"></div> <div class="controls"> <div class="input-container"> <h2>Keyboard 5000</h2> <div class="input-buttons"> <div class="demo-buttons"> <div> <button class="demo-button demo1"></button> <div>1</div> </div> <div> <button class="demo-button demo2"></button> <div>2</div> </div> <div> <button class="demo-button demo3"></button> <div>3</div> </div> <div> <button class="demo-button demo4"></button> <div>4</div> </div> <div> <button class="help"></button> <div>Help</div> </div> </div> <div class="demo-label">Demos</div> </div> </div> <div class="inputs"> <input type="range" class="volume" step="0.1" min="0" max="1"></input> <input type="range" class="tempo" min="2" max="8"></input> </div> <div class="input-labels"> <div>Volume</div> <div>Tempo</div> </div> </div> <div class="speakers"></div> </div> <!--Keyboard--> <div class="keyboard"> <div data-note="c4" data-key="81" class="key white oct">q</div> <div data-note="db4" data-key="50" class="key black black1 oct">2</div> <div data-note="d4" data-key="87" class="key white oct">w</div> <div data-note="eb4" data-key="51" class="key black black2 oct">3</div> <div data-note="e4" data-key="69" class="key white oct">e</div> <div data-note="f4" data-key="82" class="key white oct">r</div> <div data-note="gb4" data-key="53" class="key black black3 oct">5</div> <div data-note="g4" data-key="84" class="key white oct">t</div> <div data-note="ab4" data-key="54" class="key black black4 oct">6</div> <div data-note="a4" data-key="89" class="key white oct">y</div> <div data-note="bb4" data-key="55" class="key black black5 oct">7</div> <div data-note="b4" data-key="85" class="key white oct">u</div> <div data-note="c5" data-key="88" class="key white">x</div> <div data-note="db5" data-key="68" class="key black black6">d</div> <div data-note="d5" data-key="67" class="key white">c</div> <div data-note="eb5" data-key="70" class="key black black7">f</div> <div data-note="e5" data-key="86" class="key white">v</div> <div data-note="f5" data-key="66" class="key white">b</div> <div data-note="gb5" data-key="72" class="key black black8">h</div> <div data-note="g5" data-key="78" class="key white">n</div> <div data-note="ab5" data-key="74" class="key black black9">j</div> <div data-note="a5" data-key="77" class="key white">m</div> <div data-note="bb5" data-key="75" class="key black black10">k</div> <div data-note="b5" data-key="188" class="key white">,</div> <div data-note="c6" data-key="190" class="key white">.</div> </div>
</div> <script src="js/index.js"></script>
</body>
</html>
Playable Piano Keyboard with Demos - Script Codes CSS Codes
html { font-family: 'Condiment', cursive; text-align: center; font-size: 20px;
}
@media (max-width: 700px) { html { font-size: 14px; }
}
@media (max-width: 500px) { html { font-size: 10px; }
}
body { background-color: #666;
}
.wrap { display: flex; flex-direction: column; max-width: 1000px; margin: 50px auto; background: #111; border-radius: 10px; box-shadow: 10px 2px 10px #090909, 2px 10px 10px #090909;
}
.controls-container { display: flex; width: 100%; justify-content: space-around;
}
.speakers { width: 200px; height: 5px; background: #000; margin: 40px 0 0; box-shadow: 0 15px #000, 0 30px #000, 0 45px #000, 0 60px #000, 0 75px #000;
}
@media (max-width: 600px) { .speakers { display: none; }
}
.controls { width: 600px; color: white; display: flex; flex-direction: column; align-items: center;
}
.controls .input-container { display: flex;
}
.controls .input-container h2 { font-size: 1.48rem;
}
.controls .input-container .input-buttons { padding: 1em 0 0 2.5em;
}
.controls .input-container .input-buttons .demo-buttons { display: flex;
}
.controls .input-container .input-buttons .demo-label { padding-right: 40px;
}
.controls .input-container .input-buttons button { background: #7f0101; border-radius: 5%; border: none; padding: 10px 20px; margin: 0 2px 5px; cursor: pointer;
}
.controls .input-container .input-buttons button.on { background: #e40202; box-shadow: 0px 0px 2px 2px #b20101;
}
.controls .input-container .input-buttons button.help { background: #006b10;
}
.controls .input-container .input-buttons button.help.on { background: #00d11f; box-shadow: 0px 0px 2px 2px #00d11f;
}
.controls .inputs { display: flex;
}
.controls .inputs input { padding: 0 10px;
}
.controls .inputs input.tempo { transform: rotateY(180deg);
}
.controls .input-labels { display: flex; justify-content: space-around;
}
.controls .input-labels > div { padding: 0 4.5em;
}
.keyboard { width: 95%; height: 160px; display: flex; margin: 10px auto 10px; position: relative;
}
.white, .black { display: flex; align-items: flex-end; justify-content: center; font-size: 2rem; border-radius: 5px; border: 2px solid black; font-family: sans-serif;
}
.white { height: 100%; width: 12.5%; background-color: ivory; box-shadow: 2px 7px 2px #222222;
}
.white.played { background-color: #DDDDDD; transform: translate(0, 2px);
}
.black { height: 70%; width: 3%; position: absolute; z-index: 2; margin-left: -1.6%; background-color: black; color: white;
}
@media (max-width: 600px) { .black { width: 6%; }
}
.black.played { background-color: #333333; transform: translate(0, 2px);
}
.black.black1 { left: 6.7%;
}
.black.black2 { left: 13.3%;
}
.black.black3 { left: 26.7%;
}
.black.black4 { left: 33.4%;
}
.black.black5 { left: 40%;
}
.black.black6 { left: 53.3%;
}
@media (max-width: 600px) { .black.black6 { left: 11%; }
}
.black.black7 { left: 60%;
}
@media (max-width: 600px) { .black.black7 { left: 23%; }
}
.black.black8 { left: 73.3%;
}
@media (max-width: 600px) { .black.black8 { left: 48.5%; }
}
.black.black9 { left: 80%;
}
@media (max-width: 600px) { .black.black9 { left: 61%; }
}
.black.black10 { left: 86.7%;
}
@media (max-width: 600px) { .black.black10 { left: 73%; }
}
@media (max-width: 600px) { .oct { display: none; }
}
input[type=range] { -webkit-appearance: none; margin: 10px 0; width: 100%;
}
input[type=range]:focus { outline: none;
}
input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 2px; cursor: pointer; animate: 0.2s; box-shadow: 1px 1px 1px #000000; background: #000000; border-radius: 0px; border: 1px solid #000000;
}
input[type=range]::-webkit-slider-thumb { box-shadow: 1px 1px 1px #000000; border: 1px solid #000000; height: 20px; width: 10px; border-radius: 5px; background: #808080; cursor: pointer; -webkit-appearance: none; margin-top: -10px;
}
input[type=range]:focus::-webkit-slider-runnable-track { background: #000000;
}
input[type=range]::-moz-range-track { width: 100%; height: 2px; cursor: pointer; animate: 0.2s; box-shadow: 1px 1px 1px #000000; background: #000000; border-radius: 0px; border: 1px solid #000000;
}
input[type=range]::-moz-range-thumb { box-shadow: 1px 1px 1px #000000; border: 1px solid #000000; height: 20px; width: 10px; border-radius: 5px; background: #808080; cursor: pointer;
}
input[type=range]::-ms-track { width: 100%; height: 2px; cursor: pointer; animate: 0.2s; background: transparent; border-color: transparent; color: transparent;
}
input[type=range]::-ms-fill-lower { background: #000000; border: 1px solid #000000; border-radius: 0px; box-shadow: 1px 1px 1px #000000;
}
input[type=range]::-ms-fill-upper { background: #000000; border: 1px solid #000000; border-radius: 0px; box-shadow: 1px 1px 1px #000000;
}
input[type=range]::-ms-thumb { box-shadow: 1px 1px 1px #000000; border: 1px solid #000000; height: 20px; width: 10px; border-radius: 5px; background: #808080; cursor: pointer;
}
input[type=range]:focus::-ms-fill-lower { background: #000000;
}
input[type=range]:focus::-ms-fill-upper { background: #000000;
}
Playable Piano Keyboard with Demos - Script Codes JS Codes
"use strict";
/* HTML Audio API responsive piano/keyboard -TO DO test on mobile Demo 1 - No Suprises - Radiohead Demo 2 - Life on Mars - David Bowie Demo 3 - Für Elise - Ludwig van Beethoven Demo 4 - The Entertainer - Scott Joplin Increase tempo before you play a demo to play the song faster
*/
document.addEventListener("DOMContentLoaded", function () { //Frequencies list from http://www.phy.mtu.edu var frequencies = [["rest", 0], ["b3", 233.08], ["c4", 261.63], ["db4", 277.18], ["d4", 293.66], ["eb4", 311.13], ["e4", 329.63], ["f4", 349.23], ["gb4", 369.99], ["g4", 392.00], ["ab4", 415.30], ["a4", 440.00], ["bb4", 466.16], ["b4", 493.88], ["c5", 523.25], ["db5", 554.37], ["d5", 587.33], ["eb5", 622.25], ["e5", 659.25], ["f5", 698.46], ["gb5", 739.99], ["g5", 783.99], ["ab5", 830.61], ["a5", 880.00], ["bb5", 932.33], ["b5", 987.77], ["c6", 1046.50], ["d6", 1174.66], ["e6", 1318.51]]; //Songs //Note followed by note length. Crotchet = 100 var noSuprises = [["rest", 0], ["a5", 50], ["c5", 50], ["f5", 50], ["c5", 50], ["a5", 50], ["c5", 50], ["f5", 50], ["c5", 50], ["a5", 50], ["c5", 50], ["f5", 50], ["c5", 50], ["bb4", 50], ["db5", 50], ["f5", 50], ["g5", 50], ["a5", 50], ["c5", 50], ["f5", 50], ["c5", 50], ["a5", 50], ["c5", 50], ["f5", 50], ["c5", 50], ["a5", 50], ["c5", 50], ["f5", 50], ["c5", 50], ["bb4", 50], ["db5", 50], ["f5", 50], ["g5", 50], ["a4", 200], ["c4", 200], ["a4", 50], ["a4", 100], ["g4", 200], ["a4", 50], ["a4", 200], ["b3", 150], ["rest", 25], ["b3", 25], ["a4", 50], ["a4", 100], ["g4", 100], ["f4", 100], ["bb4", 200], ["d4", 200], ["e4", 50], ["e4", 100], ["f4", 100], ["g4", 100], ["a4", 250]]; var lifeOnMars = [["rest", 0], ["ab4", 50], ["bb4", 50], ["c5", 50], ["db5", 50], ["c5", 50], ["bb4", 100], ["ab4", 50], ["c5", 100], ["rest", 200], ["ab4", 50], ["bb4", 50], ["c5", 50], ["db5", 50], ["c5", 50], ["bb4", 100], ["ab4", 50], ["f5", 100], ["rest", 200], ["db5", 50], ["eb5", 50], ["f5", 50], ["gb5", 50], ["f5", 50], ["eb5", 100], ["db5", 50], ["f5", 150], ["rest", 150], ["db5", 50], ["eb5", 50], ["f5", 50], ["gb5", 50], ["f5", 50], ["eb5", 100], ["db5", 50], ["db5", 100], ["bb5", 200], ["f5", 200], ["eb5", 50], ["eb5", 50], ["eb5", 50], ["d5", 50], ["bb4", 100], ["c5", 100], ["rest", 50], ["bb5", 100], ["f5", 200], ["eb5", 50], ["eb5", 50], ["d5", 100], ["c5", 100], ["d5", 100], ["c5", 200], ["rest", 150], ["c5", 50], ["c5", 50], ["c5", 50], ["d5", 50], ["c5", 50], ["f5", 100], ["eb5", 25], ["d5", 25], ["c5", 100], ["rest", 150], ["bb4", 50], ["bb4", 50], ["bb4", 50], ["c5", 50], ["bb4", 100], ["bb5", 200], ["f5", 200], ["eb5", 50], ["eb5", 50], ["eb5", 50], ["d5", 50], ["bb4", 100], ["c5", 100], ["rest", 50], ["bb5", 100], ["f5", 200], ["eb5", 50], ["eb5", 50], ["eb5", 50], ["d5", 50], ["c5", 50], ["d5", 50], ["c5", 100], ["rest", 300], ["c5", 50], ["c5", 50], ["c5", 50], ["c5", 50], ["d5", 50], ["c5", 50], ["f5", 100], ["eb5", 25], ["d5", 25], ["c5", 100], ["rest", 200], ["bb4", 50], ["bb4", 50], ["bb4", 50], ["c5", 50], ["bb4", 100], ["bb5", 600]]; var furElise = [["rest", 0], ["e5", 25], ["eb5", 25], ["e5", 25], ["eb5", 25], ["e5", 25], ["b4", 25], ["d5", 25], ["c5", 25], ["a4", 50], ["rest", 25], ["c4", 25], ["e4", 25], ["a4", 25], ["b4", 50], ["rest", 25], ["e4", 25], ["ab4", 25], ["b4", 25], ["c5", 50], ["rest", 25], ["e4", 25], ["e5", 25], ["eb5", 25], ["e5", 25], ["eb5", 25], ["e5", 25], ["b4", 25], ["d5", 25], ["c5", 25], ["a4", 50], ["rest", 25], ["c4", 25], ["e4", 25], ["a4", 25], ["b4", 50], ["rest", 25], ["e4", 25], ["c5", 25], ["b4", 25], ["a4", 50], ["rest", 25], ["b4", 25], ["c5", 25], ["d5", 25], ["e5", 75], ["g4", 25], ["f5", 25], ["e5", 25], ["d5", 75], ["f4", 25], ["e5", 25], ["d5", 25], ["c5", 75], ["e4", 25], ["d5", 25], ["c5", 25], ["b4", 50], ["rest", 25], ["e4", 25], ["e5", 25], ["rest", 25], ["e5", 25], ["e6", 25], ["rest", 25], ["eb5", 25], ["e5", 50], ["rest", 25], ["eb5", 25], ["e5", 25], ["eb5", 25], ["e5", 25], ["eb5", 25], ["e5", 25], ["b4", 25], ["d5", 25], ["c5", 25], ["a4", 100]]; var theEntertainer = [["rest", 0], ["d6", 50], ["e6", 50], ["c6", 50], ["a5", 100], ["b5", 50], ["g5", 100], ["d5", 50], ["e5", 50], ["c5", 50], ["a4", 100], ["b4", 50], ["g4", 100], ["d5", 50], ["e5", 50], ["c5", 50], ["a4", 100], ["b4", 50], ["a4", 50], ["ab4", 50], ["g4", 100], ["rest", 50], ["g5", 100], ["d4", 50], ["d4", 50], ["e4", 50], ["c5", 100], ["e4", 50], ["c5", 100], ["e4", 50], ["c5", 300], ["c5", 50], ["d5", 50], ["eb5", 50], ["e5", 50], ["c5", 50], ["d5", 50], ["e5", 100], ["b4", 50], ["d5", 100], ["c5", 300], ["d4", 50], ["d4", 50], ["e4", 50], ["c5", 100], ["e4", 50], ["c5", 100], ["e4", 50], ["c5", 300], ["a4", 50], ["g4", 50], ["gb4", 50], ["a4", 50], ["c5", 50], ["e5", 100], ["d5", 50], ["c5", 50], ["a4", 50], ["d5", 300], ["d4", 50], ["d4", 50], ["e4", 50], ["c5", 100], ["e4", 50], ["c5", 100], ["e4", 50], ["c5", 300], ["c5", 50], ["d5", 50], ["eb5", 50], ["e5", 50], ["c5", 50], ["d5", 50], ["e5", 100], ["b4", 50], ["d5", 100], ["c5", 300], ["c5", 50], ["d5", 50], ["e5", 50], ["c5", 50], ["d5", 50], ["e5", 100], ["c5", 50], ["d5", 50], ["c5", 50], ["e5", 50], ["c5", 50], ["d5", 50], ["e5", 100], ["c5", 50], ["d5", 50], ["c5", 50], ["e5", 50], ["c5", 50], ["d5", 50], ["e5", 100], ["b4", 50], ["d5", 100], ["c5", 250]]; var demoButtons = Array.from(document.querySelectorAll('.demo-button')); var tempoInput = document.querySelector('.tempo'); var volumeInput = document.querySelector('.volume'); var blackKey = Array.from(document.querySelectorAll('.black')); var whiteKey = Array.from(document.querySelectorAll('.white')); var help = document.querySelector('.help'); var key = Array.from(document.querySelectorAll('.key')); var volume = 0.5; //Lower value = faster speed var tempo = 5; //Create new audio context when note played function playNote(note, length) { var AudioContext = window.AudioContext || window.webkitAudioContext, ctx = new AudioContext(), oscillator = ctx.createOscillator(), gainNode = ctx.createGain(); oscillator.type = 'triangle'; oscillator.frequency.value = note; gainNode.gain.value = volume; oscillator.connect(gainNode); gainNode.connect(ctx.destination); oscillator.start(0); //Trying to prevent popping sound on note end. Probably can be improved gainNode.gain.setTargetAtTime(0, length / 1000 - 0.05, 0.08); oscillator.stop(ctx.currentTime + (length / 1000 + 0.2)); oscillator.onended = function () { return ctx.close(); }; } //Finds clicked element returns data-note value and runs playKey function function onClickPlay(e) { var key = 0; var length = 300; var noteClass = e.target.dataset.note; for (var i = 0; i < frequencies.length; i++) { if (frequencies[i][0] === noteClass) { key = frequencies[i][1]; } } addVisual(e.target); playNote(key, length); } //Finds pressed key and returns data-note value function keyDownSearch(event) { var key = 0; var length = 300; var keyPressed = document.querySelector("div[data-key=\"" + event.keyCode + "\"]"); if (keyPressed === null) { return; } var note = keyPressed.dataset.note; for (var i = 0; i < frequencies.length; i++) { if (frequencies[i][0] === note) { key = frequencies[i][1]; } } addVisual(keyPressed); playNote(key, length); } //add each note to setinterval and playNote function demo(arr, e) { var noteLength = 0; e.target.classList.add('on'); tempoInput.disabled = true; demoButtons.forEach(function (btn) { btn.disabled = true; }); var _loop = function _loop(i) { noteLength += arr[i - 1][2] * tempo; setTimeout(function () { playNote(arr[i][1], arr[i][2] * tempo); if (arr[i][1] !== 0) { document.querySelector("[data-note=" + arr[i][0] + "]").classList.add('played'); } setTimeout(function () { if (arr[i][1] !== 0) { document.querySelector("[data-note=" + arr[i][0] + "]").classList.remove('played'); } if (arr.length - 2 < i) { e.target.classList.remove('on'); tempoInput.disabled = false; demoButtons.forEach(function (btn) { btn.disabled = false; }); } }, arr[i][2] * tempo - 0.05); }, noteLength); }; for (var i = 1; i < arr.length; i++) { _loop(i); } } //map notes in song to frequencies function findFrequencies(song, e) { var arr = []; song.forEach(function (note) { frequencies.forEach(function (frequency) { if (note[0] === frequency[0]) { arr.push([note[0], frequency[1], note[1]]); } }); }); demo(arr, e); } //play demo according to which one selected function demoHandler(e) { if (e.target.classList.contains('demo1')) { findFrequencies(noSuprises, e); } if (e.target.classList.contains('demo2')) { findFrequencies(lifeOnMars, e); } if (e.target.classList.contains('demo3')) { findFrequencies(furElise, e); } if (e.target.classList.contains('demo4')) { findFrequencies(theEntertainer, e); } } //input handlers function updateTempo(e) { tempo = e.target.value; } function updateVolume(e) { volume = e.target.value; } //adds css class when note played function addVisual(key, length) { key.classList.add('played'); setTimeout(function () { key.classList.remove('played'); }, length || 300); } //keyboard information toggle var helpOn = true; function helpToggle() { if (helpOn) { blackKey.forEach(function (key) { key.style.color = 'rgba(0,0,0,0)'; }); whiteKey.forEach(function (key) { key.style.color = 'rgba(255,255,255,0)'; }); help.classList.remove('on'); helpOn = !helpOn; } else { blackKey.forEach(function (key) { key.style.color = 'rgba(255,255,255,1)'; }); whiteKey.forEach(function (key) { key.style.color = 'rgba(0,0,0,1)'; }); help.classList.add('on'); helpOn = !helpOn; } } //event listeners help.addEventListener('click', helpToggle); demoButtons.forEach(function (key) { key.addEventListener('click', demoHandler); }); key.forEach(function (key) { key.addEventListener('click', onClickPlay); }); window.addEventListener('keydown', keyDownSearch); tempoInput.addEventListener('change', updateTempo); volumeInput.addEventListener('change', updateVolume); //Hide keyboard help letters on load helpToggle();
});
Developer | Adam |
Username | rzencoder |
Uploaded | November 28, 2022 |
Rating | 3 |
Size | 10,019 Kb |
Views | 8,096 |
Find the perfect freelance services for your business! Fiverr's mission is to change how the world works together. Fiverr connects businesses with freelancers offering digital services in 500+ categories. Find Developer!
Name | Size |
The Crystal Maze | 16,117 Kb |
Wikipedia Viewer | 3,276 Kb |
Placeholder Portfolio | 7,180 Kb |
React Game of Life | 7,264 Kb |
Scrolling Effects Practice | 6,441 Kb |
CSS World Flags | 8,782 Kb |
Markdown Previewer | 3,929 Kb |
React Leaderboard | 4,333 Kb |
Random Movie Quote Generator | 3,861 Kb |
React Betting App | 6,005 Kb |
Jasper is the AI Content Generator that helps you and your team break through creative blocks to create amazing, original content 10X faster. Discover all the ways the Jasper AI Content Platform can help streamline your creative workflows. Start For Free!
Name | Username | Size |
Segments mouse following | Nosir | 2,909 Kb |
A Pen by Miro Olma | Programiro | 2,342 Kb |
Project MMetro beta | Atomicsong | 5,157 Kb |
3D-box | Parthviroja | 2,346 Kb |
Tab panels | Accessibility | 0 Kb |
Octopus Bar iPad App Interactions | Davidkpiano | 6,735 Kb |
TinFoil Boats | Chandralil | 4,577 Kb |
AngularJS Skills | Supro | 3,312 Kb |
Font stack | Adrianjacob | 1,868 Kb |
Css or Czz.. | Judag | 4,111 Kb |
Surf anonymously, prevent hackers from acquiring your IP address, send anonymous email, and encrypt your Internet connection. High speed, ultra secure, and easy to use. Instant setup. Hide Your IP Now!