UNPKG

strumming-metronome

Version:

A simple JavaScript metronome for strumming practice.

933 lines (899 loc) 30.6 kB
const metronomeTables = { 44: ` <table id="measure-table"> <tr> <td colspan="4"> <span id="beat1" class="metronome-beat"><strong>1</strong></span> </td> <td colspan="4"> <span id="beat2" class="metronome-beat"><strong>2</strong></span> </td> <td colspan="4"> <span id="beat3" class="metronome-beat"><strong>3</strong></span> </td> <td colspan="4"> <span id="beat4" class="metronome-beat"><strong>4</strong></span> </td> </tr> <tr> <td> <button id="down-1.0" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-1.25" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-1.50" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-1.75"class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-2.0" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-2.25" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-2.50" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-2.75" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-3.0" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-3.25" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-3.50" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-3.75" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-4.0" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-4.25" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-4.50" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-4.75" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> </tr> <tr> <td colspan="16" class="strings-cell"> <hr class="guitar-string-6"> <hr class="guitar-string-5"> <hr class="guitar-string-4"> <hr class="guitar-string-3"> <hr class="guitar-string-2"> <hr class="guitar-string-1"> </td> </tr> <tr> <td> <button id="up-1.0" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-1.25" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-1.50" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-1.75" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-2.0" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-2.25" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-2.50" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-2.75" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-3.0" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-3.25" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-3.50" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-3.75" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-4.0" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-4.25" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-4.50" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-4.75" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> </tr> </table> `, 34: ` <table id="measure-table"> <tr> <td colspan="4"> <span id="beat1" class="metronome-beat"><strong>1</strong></span> </td> <td colspan="4"> <span id="beat2" class="metronome-beat"><strong>2</strong></span> </td> <td colspan="4"> <span id="beat3" class="metronome-beat"><strong>3</strong></span> </td> </tr> <tr> <td> <button id="down-1.0" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-1.25" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-1.50" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-1.75"class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-2.0" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-2.25" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-2.50" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-2.75" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-3.0" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-3.25" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-3.50" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-3.75" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> </tr> <tr> <td colspan="16" class="strings-cell"> <hr class="guitar-string-6"> <hr class="guitar-string-5"> <hr class="guitar-string-4"> <hr class="guitar-string-3"> <hr class="guitar-string-2"> <hr class="guitar-string-1"> </td> </tr> <tr> <td> <button id="up-1.0" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-1.25" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-1.50" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-1.75" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-2.0" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-2.25" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-2.50" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-2.75" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-3.0" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-3.25" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-3.50" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-3.75" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> </tr> </table> `, 68: ` <table id="measure-table"> <tr> <td colspan="2"> <span id="beat1" class="metronome-beat"><strong>1</strong></span> </td> <td colspan="2"> <span id="beat2" class="metronome-beat"><strong>2</strong></span> </td> <td colspan="2"> <span id="beat3" class="metronome-beat"><strong>3</strong></span> </td> <td colspan="2"> <span id="beat4" class="metronome-beat"><strong>4</strong></span> </td> <td colspan="2"> <span id="beat5" class="metronome-beat"><strong>5</strong></span> </td> <td colspan="2"> <span id="beat6" class="metronome-beat"><strong>6</strong></span> </td> </tr> <tr> <td> <button id="down-1.0" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-1.50" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-2.0" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-2.50" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-3.0" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-3.50" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-4.0" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-4.50" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-5.0" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-5.50" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-6.0" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> <td> <button id="down-6.50" class="metronome-arrow-down-btn"> <i class="metronome-arrow-down-black-icon"></i> </button> </td> </tr> <tr> <td colspan="16" class="strings-cell"> <hr class="guitar-string-6"> <hr class="guitar-string-5"> <hr class="guitar-string-4"> <hr class="guitar-string-3"> <hr class="guitar-string-2"> <hr class="guitar-string-1"> </td> </tr> <tr> <td> <button id="up-1.0" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-1.50" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-2.0" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-2.50" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-3.0" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-3.50" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-4.0" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-4.50" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-5.0" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-5.50" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-6.0" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> <td> <button id="up-6.50" class="metronome-arrow-up-btn"> <i class="metronome-arrow-up-black-icon"></i> </button> </td> </tr> </table> ` }; const metronomeContainerHTML = ` <div id="metronome-controller"> <label for="metronome-time-signature">Time Signature:</label> <select id="metronome-time-signature"> <option value="44">4/4</option> <option value="34">3/4</option> <option value="68">6/8</option> </select> <br/> <input id="bpm-input" type="number" value="60" min="30" max="300"> <span class="bpm-unit">bpm</span> <br/> <button id="metronome-btn"> <i id="metronome-icon" class="metronome-play-icon"></i> <span id="metronome-text">Play</span> </button> </div> <div id="metronome-table"> </div> `; const metronomeCSS = ` #metronome-container { padding: 10px; overflow: auto; /* Enable scrolling if content overflows */ } #bpm-input { margin-top: 5px; padding: 5px; } #metronome-time-signature { padding: 5px; } .bpm-unit { margin-right: 10px; } #metronome-btn { margin-top: 10px; padding: 5px; background: #28a745; color: #fff !important; border: none; cursor: pointer; border-radius: 0.125rem; } #metronome-btn.running { background: #dc3545; } #metronome-controller { margin: 20px; } #measure-table { margin: 20px; } .metronome-play-icon { background: url("./assets/images/play.svg") no-repeat center; display: inline-block; width: 10px; height: 10px; } .metronome-stop-icon { background: url("./assets/images/stop.svg") no-repeat center; display: inline-block; width: 10px; height: 10px; } .metronome-arrow-up-black-icon { background: url("./assets/images/arrow-up-black.svg") no-repeat center; display: inline-block; width: 15px; height: 15px; } .metronome-arrow-down-black-icon { background: url("./assets/images/arrow-down-black.svg") no-repeat center; display: inline-block; width: 15px; height: 15px; } .metronome-arrow-up-blue-icon { background: url("./assets/images/arrow-up-blue.svg") no-repeat center; display: inline-block; width: 15px; height: 15px; } .metronome-arrow-down-blue-icon { background: url("./assets/images/arrow-down-blue.svg") no-repeat center; display: inline-block; width: 15px; height: 15px; } .metronome-arrow-up-white-icon { background: url("./assets/images/arrow-up-white.svg") no-repeat center; display: inline-block; width: 15px; height: 15px; } .metronome-arrow-down-white-icon { background: url("./assets/images/arrow-down-white.svg") no-repeat center; display: inline-block; width: 15px; height: 15px; } .guitar-string-1 { border-top: 0.25px solid #000; /* String 1 (thinnest) */ } .guitar-string-2 { border-top: 0.5px solid #000; } .guitar-string-3 { border-top: 1px solid #000; } .guitar-string-4 { border-top: 1.5px solid #000; } .guitar-string-5 { border-top: 2px solid #000; } .guitar-string-6 { border-top: 2.5px solid #000; /* String 6 (thickest) */ } .metronome-beat { margin-left: 10px; } .metronome-arrow-up-btn { padding-top: 3px; cursor: pointer; background-color: #fff; color: black; border-width: 1px; border-style: outset; border-color: black; border-radius: 0.125rem; } .metronome-arrow-down-btn { padding-top: 3px; cursor: pointer; background-color: #fff; color: black; border-width: 1px; border-style: outset; border-color: black; border-radius: 0.125rem; } .metronome-selected-button { padding-top: 3px; cursor: pointer; background-color: #D3D3D3; color: blue; border-width: 1px; border-style: outset; border-color: blue; border-radius: 0.125rem; } .metronome-active-btn { background-color: blue; color: white; border-width: 1px; border-style: outset; border-color: blue; border-radius: 0.125rem; } `; const beatIds = { 44: ["beat1", "beat2", "beat3", "beat4"], 34: ["beat1", "beat2", "beat3"], 68: ["beat1", "beat2", "beat3", "beat4", "beat5", "beat6"] } const upQuarterBeatIds = { 44: [ "up-1.0", "up-1.25", "up-1.50", "up-1.75", "up-2.0", "up-2.25", "up-2.50", "up-2.75", "up-3.0", "up-3.25", "up-3.50", "up-3.75", "up-4.0", "up-4.25", "up-4.50", "up-4.75" ], 34: [ "up-1.0", "up-1.25", "up-1.50", "up-1.75", "up-2.0", "up-2.25", "up-2.50", "up-2.75", "up-3.0", "up-3.25", "up-3.50", "up-3.75" ], 68: [ "up-1.0", "up-1.50", "up-2.0", "up-2.50", "up-3.0", "up-3.50", "up-4.0", "up-4.50", "up-5.0", "up-5.50", "up-6.0", "up-6.50" ] }; const downQuarterBeatIds = { 44: [ "down-1.0", "down-1.25", "down-1.50", "down-1.75", "down-2.0", "down-2.25", "down-2.50", "down-2.75", "down-3.0", "down-3.25", "down-3.50", "down-3.75", "down-4.0", "down-4.25", "down-4.50", "down-4.75" ], 34: [ "down-1.0", "down-1.25", "down-1.50", "down-1.75", "down-2.0", "down-2.25", "down-2.50", "down-2.75", "down-3.0", "down-3.25", "down-3.50", "down-3.75" ], 68: [ "down-1.0", "down-1.50", "down-2.0", "down-2.50", "down-3.0", "down-3.50", "down-4.0", "down-4.50", "down-5.0", "down-5.50", "down-6.0", "down-6.50" ] } const downStrum = new Audio("./assets/sounds/down-strum.mp3"); const upStrum = new Audio("./assets/sounds/up-strum.mp3"); function unlockAudio() { const context = new (window.AudioContext || window.webkitAudioContext)(); const buffer = context.createBuffer(1, 1, 22050); const source = context.createBufferSource(); source.buffer = buffer; source.connect(context.destination); source.start(0); document.removeEventListener('touchstart', unlockAudio); } function selectMetronome(timeSelection) { // Remove listeners for other time signatures const oldButton = document.getElementById("metronome-btn"); const button = oldButton.cloneNode(true); oldButton.parentNode.replaceChild(button, oldButton); // Inject Table into the page const metronomeTable = document.querySelector("#metronome-table"); metronomeTable.innerHTML = metronomeTables[`${timeSelection}`]; // Add event listeners to toggle the class btn classes metronomeTable.querySelectorAll(".metronome-arrow-up-btn").forEach(button => { button.addEventListener("click", () => { button.classList.toggle("metronome-selected-button"); if (button.firstElementChild.className === "metronome-arrow-up-black-icon") { button.firstElementChild.className = "metronome-arrow-up-blue-icon"; } else { button.firstElementChild.className = "metronome-arrow-up-black-icon"; } }); }); metronomeTable.querySelectorAll(".metronome-arrow-down-btn").forEach(button => { button.addEventListener("click", () => { button.classList.toggle("metronome-selected-button"); if (button.firstElementChild.className === "metronome-arrow-down-black-icon") { button.firstElementChild.className = "metronome-arrow-down-blue-icon"; } else { button.firstElementChild.className = "metronome-arrow-down-black-icon"; } }); }); // Get references to elements const container = document.querySelector("#metronome-container"); const bpmInput = container.querySelector("#bpm-input"); const icon = container.querySelector("#metronome-icon"); const text = container.querySelector("#metronome-text"); const timeSignature = container.querySelector("#metronome-time-signature"); // Store elements const beats = beatIds[`${timeSelection}`].map(id => document.getElementById(id)); const upQuarterBeatButtons = upQuarterBeatIds[`${timeSelection}`].map(id => document.getElementById(id)); const downQuarterBeatButtons = downQuarterBeatIds[`${timeSelection}`].map(id => document.getElementById(id)); let currentBeatIndex = 0; // Track the current beat let interval; function playMetronome() { if (interval) { clearInterval(interval); interval = null; icon.classList.remove("metronome-stop-icon"); icon.classList.add("metronome-play-icon"); text.textContent = "Play"; button.classList.remove("running"); // Reset all beats and arrows beats.forEach(beat => beat.style.color = "black"); downQuarterBeatButtons.forEach(btn => { if (btn.classList.contains("metronome-selected-button")) { btn.firstElementChild.className = "metronome-arrow-down-blue-icon"; } else { btn.firstElementChild.className = "metronome-arrow-down-black-icon"; } btn.classList.remove("metronome-active-btn"); }); upQuarterBeatButtons.forEach(btn => { if (btn.classList.contains("metronome-selected-button")) { btn.firstElementChild.className = "metronome-arrow-up-blue-icon"; } else { btn.firstElementChild.className = "metronome-arrow-up-black-icon"; } btn.classList.remove("metronome-active-btn"); }); currentBeatIndex = 0; // Enable controls when stopping timeSignature.removeAttribute("disabled"); bpmInput.removeAttribute("disabled"); upQuarterBeatButtons.forEach(btn => btn.removeAttribute("disabled")); downQuarterBeatButtons.forEach(btn => btn.removeAttribute("disabled")); } else { const bpm = parseInt(bpmInput.value, 10); let subBeat = 0; // Tracks which quarter note or half note we are one let activeDownButton = document.getElementById('down-1.0'); let activeUpButton = document.getElementById('up-1.0'); if (activeDownButton.classList.contains("metronome-selected-button")) { activeDownButton.firstElementChild.className = "metronome-arrow-down-white-icon"; activeDownButton.classList.add("metronome-active-btn"); downStrum.play(); } if (activeUpButton.classList.contains("metronome-selected-button")) { activeUpButton.firstElementChild.className = "metronome-arrow-up-white-icon"; activeUpButton.classList.add("metronome-active-btn"); upStrum.play(); } // Highlight the first beat initially beats[currentBeatIndex].style.color = "red"; //console.log("Tick - Beat", 1, "SubBeat:", "1.0"); // Debug log let beatDivide = 4; let subBeatMultiply = 25; if (timeSelection === 68) { beatDivide = 2; subBeatMultiply = 50; } interval = setInterval(() => { // Reset all arrows downQuarterBeatButtons.forEach(btn => { if (btn.classList.contains("metronome-selected-button")) { btn.firstElementChild.className = "metronome-arrow-down-blue-icon"; } else { btn.firstElementChild.className = "metronome-arrow-down-black-icon"; } btn.classList.remove("metronome-active-btn"); }); upQuarterBeatButtons.forEach(btn => { if (btn.classList.contains("metronome-selected-button")) { btn.firstElementChild.className = "metronome-arrow-up-blue-icon"; } else { btn.firstElementChild.className = "metronome-arrow-up-black-icon"; } btn.classList.remove("metronome-active-btn"); }); subBeat = (subBeat + 1) % beatDivide; if (subBeat === 0) { // If we've cycled through all 4 subBeats, move to the next beat beats[currentBeatIndex].style.color = "black"; // Reset previous beat currentBeatIndex = (currentBeatIndex + 1) % beats.length; beats[currentBeatIndex].style.color = "red"; // Highlight the new beat } // Find the matching quarter or half beat button const subBeatId = `${currentBeatIndex + 1}.${subBeat * subBeatMultiply}`; activeDownButton = document.getElementById(`down-${subBeatId}`); activeUpButton = document.getElementById(`up-${subBeatId}`); if (activeDownButton.classList.contains("metronome-selected-button")) { activeDownButton.firstElementChild.className = "metronome-arrow-down-white-icon"; activeDownButton.classList.add("metronome-active-btn"); downStrum.play(); } if (activeUpButton.classList.contains("metronome-selected-button")) { activeUpButton.firstElementChild.className = "metronome-arrow-up-white-icon"; activeUpButton.classList.add("metronome-active-btn"); upStrum.play(); } //console.log("Tick - Beat", currentBeatIndex + 1, "subBeat:", subBeatId); // Debug log }, (60 / bpm) * 1000 / beatDivide); // Divide by subBeats icon.classList.remove("metronome-play-icon"); icon.classList.add("metronome-stop-icon"); text.textContent = "Stop"; button.classList.add("running"); // Disable controls when playing timeSignature.setAttribute("disabled", true); bpmInput.setAttribute("disabled", true); upQuarterBeatButtons.forEach(btn => btn.setAttribute("disabled", true)); downQuarterBeatButtons.forEach(btn => btn.setAttribute("disabled", true)); } } button.addEventListener("click", playMetronome); }; export default function createMetronome() { document.addEventListener('touchstart', unlockAudio, false); // Inject CSS into the document if (!document.querySelector("#metronome-style")) { const style = document.createElement("style"); style.id = "metronome-style"; style.textContent = metronomeCSS; document.head.appendChild(style); } // Inject HTML into the page const container = document.querySelector("#metronome-container"); container.innerHTML = metronomeContainerHTML; const timeSignature = container.querySelector("#metronome-time-signature"); document.getElementById("metronome-time-signature").addEventListener("change", function () { const selectedValue = this.value; switch (selectedValue) { case "44": selectMetronome(44); break; case "34": selectMetronome(34); break; case "68": selectMetronome(68); break; } }); selectMetronome(44); }