From cf6322b511cab458cbd4869f98e004b173939c20 Mon Sep 17 00:00:00 2001 From: Rockingcool Date: Tue, 30 Dec 2025 16:08:18 -0600 Subject: [PATCH] Highlight each note in a chord as it's being played --- js/src/guitar-diagrams-web-component.mjs | 53 +++++++++++++++++++++--- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/js/src/guitar-diagrams-web-component.mjs b/js/src/guitar-diagrams-web-component.mjs index e47acdc..a9ca964 100644 --- a/js/src/guitar-diagrams-web-component.mjs +++ b/js/src/guitar-diagrams-web-component.mjs @@ -864,19 +864,62 @@ class GuitarDiagramsWebComponent extends HTMLElement { // play slowly let timeGap = 0; let now = Tone.now(); - allNoteFrequencies.forEach((freq) => { - this.#outputSpeaker.triggerAttack(freq, now + timeGap); + this.#markers.forEach((marker) => { + const canvas = this.shadowRoot.querySelector("canvas").getContext("2d"); + // Draw yellow after a timeout. + setTimeout(() => { + canvas.beginPath(); + canvas.fillStyle = "yellow"; + this.#drawMarkerCircle(marker.relativePosX, marker.relativePosY); + canvas.closePath(); + }, timeGap * 1000); + + this.#outputSpeaker.triggerAttack(this.markerToNoteFrequency(marker), now + timeGap); timeGap += 0.5; + + // Draw black after a timeout. This timeout is incremented by 0.5 from the 'draw yellow' one. + setTimeout(() => { + canvas.beginPath(); + canvas.fillStyle = "black"; + this.#drawMarkerCircle(marker.relativePosX, marker.relativePosY); + canvas.closePath(); + }, timeGap * 1000); }); this.#outputSpeaker.triggerRelease(allNoteFrequencies, now + timeGap + 0.5); timeGap += 0.5; - // play faster - allNoteFrequencies.forEach((freq) => { - this.#outputSpeaker.triggerAttack(freq, now + timeGap); + // Play Faster + + const canvas = this.shadowRoot.querySelector("canvas").getContext("2d"); + // Draw everything yellow + this.#markers.forEach((marker) => { + setTimeout(() => { + canvas.beginPath(); + canvas.fillStyle = "yellow"; + this.#drawMarkerCircle(marker.relativePosX, marker.relativePosY); + canvas.closePath(); + }, timeGap * 1000); + }); + + this.#markers.forEach((marker) => { + this.#outputSpeaker.triggerAttack(this.markerToNoteFrequency(marker), now + timeGap); timeGap += 0.055; }); + this.#outputSpeaker.triggerRelease(allNoteFrequencies, now + timeGap + 2); + + // Draw everything black + this.#markers.forEach((marker) => { + setTimeout( + () => { + canvas.beginPath(); + canvas.fillStyle = "black"; + this.#drawMarkerCircle(marker.relativePosX, marker.relativePosY); + canvas.closePath(); + }, + (timeGap + 1) * 1000, + ); + }); } drawAllMarkers() {