feat(04-03): BeatGrid module + enhanced beat rendering + loading states
- Create beats.js with BeatGrid class: load(), getCalibratedBeats(), getCalibratedOnsets(), snap(), hasBeats getter - BeatGrid manages calibrationOffset and snapEnabled state - snap() uses 100ms threshold against calibrated beat positions - Handles API field variants: beats/beat_times, tempo/tempo_bpm - Refactor timeline.js: replace beatTimes/calibrationOffset/snapEnabled with this.beatGrid - Add getters/setters for calibrationOffset and snapEnabled (backward compat with app.js) - render() now shows DETECTING BEATS... loading indicator and error state - render() draws beat marks via getCalibratedBeats(), onset ticks via getCalibratedOnsets() - snapToBeat() delegates to beatGrid.snap() - app.js chains BPM label update after loadBeats() resolves
This commit is contained in:
@@ -273,7 +273,13 @@ function initTimeline() {
|
||||
const path = `/app/shows/${filename}`;
|
||||
timeline.audioDuration = audio.duration;
|
||||
timeline.loadWaveform(path);
|
||||
timeline.loadBeats(path);
|
||||
// Load beats and update BPM display when analysis completes
|
||||
timeline.loadBeats(path).then(() => {
|
||||
if (timeline.beatGrid.tempoBpm) {
|
||||
const label = document.getElementById('beat-label');
|
||||
if (label) label.textContent = `${Math.round(timeline.beatGrid.tempoBpm)} BPM`;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Zoom slider
|
||||
|
||||
Reference in New Issue
Block a user