-----
We committed to learning the guitar (again). However, this time we are taking a more methodical approach vs. just getting frustrated that we don't sound like Monte Montgomery.
The internet is helpful and one of our favorite resources has been Lauren Bateman who encourages "Embace the Suck". Lauren encourages other things too... like practicing chord changes with a metronome and keeping a progress log. These two suggestions are huge. We created some simple HTML markup to help us practice random chord changes and, gotta say, you show more results with practice than with excuses.
Just copy and save the HTML markup between the "-----"s below on your hard drive as "random_guitar_chords.html" and it should work in any web browser. NOTE: There is no spyware, tracking, cookies, disk writes, etc. Feel free to edit the HTML to meet your needs.
Good luck and see you on the stage!
-----
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Guitar Chords + Metronome</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
.container {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-start;
gap: 10px;
padding: 20px;
}
.column {
padding: 10px;
}
.left-section {
width: 300px;
text-align: center;
}
.right-section {
flex-grow: 1;
border-left: 2px solid #aaa;
padding-left: 20px;
transition: background-color 0.1s;
}
#chordDisplay {
font-size: 36px;
margin-top: 30px;
}
.checkbox-container {
margin-bottom: 5px;
text-align: left;
}
#timer {
margin-top: 10px;
}
#metronomeArea {
text-align: center;
}
#bpmControls {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
margin-bottom: 15px;
}
.vertical-slider {
writing-mode: bt-lr;
-webkit-appearance: slider-vertical;
height: 100px;
accent-color: blue;
}
</style>
</head>
<body>
<div class="container">
<!-- Chord Section -->
<div class="column left-section">
<h2>Select Guitar Chords</h2>
<form id="chordForm">
<div class="checkbox-container"><input type="checkbox" id="A" value="A" checked><label for="A"> A</label></div>
<div class="checkbox-container"><input type="checkbox" id="Am" value="Am" checked><label for="Am"> Am</label></div>
<div class="checkbox-container"><input type="checkbox" id="Bm" value="Bm"><label for="Bm"> Bm</label></div>
<div class="checkbox-container"><input type="checkbox" id="C" value="C" checked><label for="C"> C</label></div>
<div class="checkbox-container"><input type="checkbox" id="D" value="D" checked><label for="D"> D</label></div>
<div class="checkbox-container"><input type="checkbox" id="E" value="E" checked><label for="E"> E</label></div>
<div class="checkbox-container"><input type="checkbox" id="Em" value="Em" checked><label for="Em"> Em</label></div>
<div class="checkbox-container"><input type="checkbox" id="F" value="F"><label for="F"> F</label></div>
<div class="checkbox-container"><input type="checkbox" id="G" value="G" checked><label for="G"> G</label></div>
</form>
<p><strong>!!! ALWAYS USE A METRONOME AND LOG YOUR PROGRESS !!!</strong></p>
<label for="initialChordsSelect">How many chords to cycle:</label><br>
<select id="initialChordsSelect">
<option value="2" selected>2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select><br><br>
<label for="timeSelect">Seconds until next random chords:</label><br>
<select id="timeSelect">
<option value="10">10</option>
<option value="20">20</option>
<option value="30" selected>30</option>
<option value="40">40</option>
</select><br><br>
<button onclick="startDisplay()">Let's Jam!</button>
<div id="chordDisplay"></div>
<div id="timer"></div>
<div id="totalMinutes"></div>
</div>
<!-- Metronome Section -->
<div class="column right-section" id="metronomeArea">
<h2>Metronome</h2>
<div id="bpmControls">
<button onclick="changeBPM(-1)">-1</button>
<span id="bpmDisplay">92</span> BPM
<button onclick="changeBPM(1)">+1</button>
</div>
<button onclick="toggleMetronome()">Start/Stop</button>
<input type="range" min="40" max="200" step="5" value="92" class="vertical-slider" id="bpmSlider" onchange="sliderChangeBPM(this.value)">
</div>
</div>
<script>
let startTime;
let timerInterval;
let bpm = 92;
let metronomeOn = false;
let intervalId;
let audioCtx = new (window.AudioContext || window.webkitAudioContext)();
let volume = 2.0;
function startDisplay() {
clearInterval(timerInterval);
document.getElementById("chordDisplay").textContent = "";
document.getElementById("timer").textContent = "";
startTime = new Date().getTime();
displayChords();
displayTimer();
}
function displayChords() {
let chords = Array.from(document.querySelectorAll('input[type="checkbox"]:checked')).map(cb => cb.value);
let num = parseInt(document.getElementById("initialChordsSelect").value);
let selected = [];
if (chords.length < num) num = chords.length;
while (selected.length < num) {
let pick = chords[Math.floor(Math.random() * chords.length)];
if (!selected.includes(pick)) selected.push(pick);
}
document.getElementById("chordDisplay").textContent = selected.join(" ");
}
function displayTimer() {
let seconds = parseInt(document.getElementById("timeSelect").value);
let count = seconds;
timerInterval = setInterval(() => {
count--;
if (count <= 0) {
clearInterval(timerInterval);
document.getElementById("timer").textContent = "";
displayChords();
displayTimer();
} else {
document.getElementById("timer").textContent = "SPACEBAR for NOW else NEW in " + count + "s";
let elapsed = ((new Date().getTime() - startTime) / (1000 * 60)).toFixed(1);
document.getElementById("totalMinutes").textContent = "Total practice time: " + elapsed + " min";
}
}, 1000);
}
function toggleMetronome() {
if (metronomeOn) {
clearInterval(intervalId);
metronomeOn = false;
document.getElementById("metronomeArea").style.backgroundColor = "";
} else {
metronomeOn = true;
beat();
intervalId = setInterval(beat, 60000 / bpm);
}
}
function beat() {
flashMetronome();
playClick();
}
function flashMetronome() {
const area = document.getElementById("metronomeArea");
area.style.backgroundColor = "#4CAF50";
setTimeout(() => area.style.backgroundColor = "", 100);
}
function playClick() {
const now = audioCtx.currentTime;
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.type = "sine";
osc.frequency.setValueAtTime(500, now);
gain.gain.setValueAtTime(volume, now);
gain.gain.exponentialRampToValueAtTime(0.001, now + 0.05);
osc.connect(gain);
gain.connect(audioCtx.destination);
osc.start(now);
osc.stop(now + 0.06);
}
function changeBPM(delta) {
bpm = Math.max(40, Math.min(200, bpm + delta));
document.getElementById("bpmDisplay").textContent = bpm;
document.getElementById("bpmSlider").value = bpm;
if (metronomeOn) {
clearInterval(intervalId);
intervalId = setInterval(beat, 60000 / bpm);
}
}
function sliderChangeBPM(val) {
bpm = parseInt(val);
document.getElementById("bpmDisplay").textContent = bpm;
if (metronomeOn) {
clearInterval(intervalId);
intervalId = setInterval(beat, 60000 / bpm);
}
}
document.body.addEventListener('keydown', e => {
if (e.code === "Space") {
e.preventDefault();
clearInterval(timerInterval);
displayChords();
displayTimer();
}
});
</script>
</body>
</html>
-----