diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-18 21:47:27 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-18 21:47:27 +0100 |
| commit | 8f069fc08a123b1544c2a978586046e1ebb2173a (patch) | |
| tree | d05b59ac439b3d93b3ed23df0110ddf29d39a4a7 /tools | |
| parent | f48397c58248ca338c258b1de762314926fe681f (diff) | |
fix(mq_editor): destroy old viewer listeners on WAV reload
Each loadAudioBuffer() was creating a new SpectrogramViewer without
removing the previous one's canvas event listeners. Old viewers would
fire on every mouse event, rendering stale spectrogram data and calling
editor.onPartialSelect() with out-of-range indices (hiding the amp panel).
Fix: store handlers as named instance properties, add destroy() to remove
them, and call destroy() before creating a new viewer.
handoff(Claude): bug fix only, no behaviour change
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/mq_editor/app.js | 1 | ||||
| -rw-r--r-- | tools/mq_editor/viewer.js | 34 |
2 files changed, 25 insertions, 10 deletions
diff --git a/tools/mq_editor/app.js b/tools/mq_editor/app.js index dd0a24f..d53af37 100644 --- a/tools/mq_editor/app.js +++ b/tools/mq_editor/app.js @@ -189,6 +189,7 @@ function loadAudioBuffer(buffer, label) { }); } + if (viewer) viewer.destroy(); viewer = new SpectrogramViewer(canvas, audioBuffer, stftCache); viewer.setFrames(peakFrames); document.getElementById('exploreBtn').disabled = false; diff --git a/tools/mq_editor/viewer.js b/tools/mq_editor/viewer.js index 1bc5fc9..923edcc 100644 --- a/tools/mq_editor/viewer.js +++ b/tools/mq_editor/viewer.js @@ -608,10 +608,19 @@ class SpectrogramViewer { this.t_center = (this.t_view_min + this.t_view_max) / 2; } + destroy() { + const {canvas} = this; + canvas.removeEventListener('mousedown', this._onMousedown); + canvas.removeEventListener('mousemove', this._onMousemove); + canvas.removeEventListener('mouseleave', this._onMouseleave); + canvas.removeEventListener('mouseup', this._onMouseup); + canvas.removeEventListener('wheel', this._onWheel); + } + setupMouseHandlers() { const {canvas, tooltip} = this; - canvas.addEventListener('mousedown', (e) => { + this._onMousedown = (e) => { const {x, y} = getCanvasCoords(e, canvas); // Explore mode: commit preview on click @@ -637,9 +646,10 @@ class SpectrogramViewer { // Otherwise: select partial by click const idx = this.hitTestPartial(x, y); this.selectPartial(idx); - }); + }; + canvas.addEventListener('mousedown', this._onMousedown); - canvas.addEventListener('mousemove', (e) => { + this._onMousemove = (e) => { const {x, y} = getCanvasCoords(e, canvas); if (this.dragState) { @@ -685,23 +695,26 @@ class SpectrogramViewer { tooltip.style.top = (e.clientY + 10) + 'px'; tooltip.style.display = 'block'; tooltip.textContent = `${time.toFixed(3)}s, ${freq.toFixed(1)}Hz, ${intensity.toFixed(1)}dB`; - }); + }; + canvas.addEventListener('mousemove', this._onMousemove); - canvas.addEventListener('mouseleave', () => { + this._onMouseleave = () => { this.mouseX = -1; this.drawMouseCursor(-1); tooltip.style.display = 'none'; - }); + }; + canvas.addEventListener('mouseleave', this._onMouseleave); - canvas.addEventListener('mouseup', () => { + this._onMouseup = () => { if (this.dragState) { this.dragState = null; canvas.style.cursor = 'crosshair'; if (this.onPartialSelect) this.onPartialSelect(this.selectedPartial); } - }); + }; + canvas.addEventListener('mouseup', this._onMouseup); - canvas.addEventListener('wheel', (e) => { + this._onWheel = (e) => { e.preventDefault(); const delta = e.deltaY !== 0 ? e.deltaY : e.deltaX; @@ -726,7 +739,8 @@ class SpectrogramViewer { this.updateViewBounds(); this.render(); - }); + }; + canvas.addEventListener('wheel', this._onWheel); } // --- Utilities --- |
