fix: canvas audioclip hiển thị theo tỉ lệ tempo, không giãn khung

This commit is contained in:
2026-08-02 18:20:48 +07:00
parent 0853a13f62
commit 9be6991222
4 changed files with 22 additions and 9 deletions
+11 -6
View File
@@ -9759,8 +9759,11 @@ const MediaExplorerPanel = ({ height }) => {
} else {
const pk = curPeaks && curPeaks.length > 0 ? curPeaks : null;
if (pk) {
const pxPerSec = 50;
const contentW = Math.max(w, dur * pxPerSec);
// Audio hin th theo t l tempo (pxPerSec), không giãn đy khung preview
const audioBpm = curTempo || 120;
const pxPerBeat = 42;
const pxPerSec = pxPerBeat * audioBpm / 60;
const contentW = Math.max(1, dur * pxPerSec);
let offset = 0;
if (playing && contentW > w && dur > 0) {
offset = Math.max(0, Math.min(contentW - w, t * pxPerSec - w / 2));
@@ -9774,7 +9777,8 @@ const MediaExplorerPanel = ({ height }) => {
const ph = Math.max(2, pk[i] * (h / 2 - 4));
ctx.fillRect(x, mid - ph, barW, ph * 2);
}
const audioPlayheadX = contentW > w ? Math.min(w / 2, t * pxPerSec) : Math.min(w, t * pxPerSec);
// Playhead theo t l tempo; khi content rng hơn frame thì khóa gia + scroll
const audioPlayheadX = contentW > w ? Math.min(w / 2, t * pxPerSec) : (t * pxPerSec);
if (playing && dur > 0) {
ctx.fillStyle = '#ef4444';
ctx.fillRect(audioPlayheadX - 1, 0, 2, h - 14);
@@ -9788,10 +9792,11 @@ const MediaExplorerPanel = ({ height }) => {
ctx.fillStyle = '#111'; ctx.fillRect(0, h - 14, w, 14);
ctx.fillStyle = '#888'; ctx.font = '9px JetBrains Mono, monospace';
const rulerBpm = curTempo || 120;
const rulerPxPerBeat = isMidiFile(f) ? 42 : (50 * 60 / rulerBpm);
const rulerPxPerBeat = 42;
const isRealMidi = isMidiFile(f) && curMidiNotes && curMidiNotes.length && curMidiTotalBeats > 0;
const rulerTotalBeats = isRealMidi ? Math.max(curMidiTotalBeats, 4) : Math.max(4, Math.ceil(dur * rulerBpm / 60) || 16);
const rulerContentW = isRealMidi ? Math.max(w, rulerTotalBeats * rulerPxPerBeat) : Math.max(w, dur * rulerPxPerBeat * rulerBpm / 60);
// T l theo tempo (không giãn đy khung)
const rulerContentW = Math.max(1, rulerTotalBeats * rulerPxPerBeat);
const rulerPxPerSec = rulerPxPerBeat * rulerBpm / 60;
const rulerOffset = (playing && rulerContentW > w && dur > 0) ? Math.max(0, Math.min(rulerContentW - w, t * rulerPxPerSec - w / 2)) : 0;
for (let b = 0; b <= rulerTotalBeats; b += 4) {
@@ -9801,7 +9806,7 @@ const MediaExplorerPanel = ({ height }) => {
}
};
React.useEffect(() => { drawCanvas(currentTime); }, [peaks, audioBuffer, midiNotes, selected, folder, isPlaying]);
React.useEffect(() => { drawCanvas(currentTime); }, [peaks, audioBuffer, audioDuration, midiNotes, selected, folder, isPlaying]);
React.useEffect(() => () => { if (rafRef.current) cancelAnimationFrame(rafRef.current); }, []);
const handleSelect = (f) => {
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -24,7 +24,7 @@
<script src="/static/js/services/midiExtractor.js?v=202607281052"></script>
<script src="/static/js/services/promptTemplateManager.js?v=202607281039"></script>
<script src="/static/js/services/undoRedoEngine.js?v=202607290941"></script>
<script src="/static/js/app.precompiled.js?v=202608021930" defer></script>
<script src="/static/js/app.precompiled.js?v=202608021936" defer></script>
<link rel="stylesheet" href="/static/css/styles.css?v=202607271016">
<style>
:root {
+5
View File
@@ -1139,3 +1139,8 @@
- **Tóm tắt thay đổi:** (1) Fix canvas audio hiển thị sai: waveform server trả `duration` nhưng không lưu → `dur=0` nên ruler/playhead/time sai. Thêm state `audioDuration` (set ở loadWaveform local/server + playSelected, clear ở handleSelect), `fileDuration` ưu tiên dùng; bar width waveform sửa theo `contentW` thay vì `w` để scroll đúng. (2) Drag & drop file từ Media Explorer vào timeline MAIN SESSION + SECTION-TAB: file row `draggable` + `onDragStart` set `window.__mediaExplorerDragFile`; App thêm `resolveMediaExplorerDropFile()` chuyển entry → real File (client handle `getFile()`, server `file_id` fetch download, local `path` fetch `/media/file`); drop handlers trên track lane + wrapper timeline xử lý cả drag ME lẫn drag OS file (MIDI → new track / audio → load vào track).
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/static/js/app.precompiled.js`, `app/templates/index.html`
- **Ghi chú/Test (nếu có):** Smoke jsdom: wav client → metadata Duration 3.00s (trước là 0); drag file row → payload text/plain=name + `__mediaExplorerDragFile` set → drop vào track lane → resolve thành File + load (uploadToServer gọi). Hard reload.
### [2026-08-02 19:36] Task: Fix canvas audioclip giãn đầy khung preview
- **Tóm tắt thay đổi:** `drawCanvas` branch audio: bỏ `contentW = Math.max(w, dur*pxPerSec)` (giãn đầy frame) → `contentW = max(1, dur*pxPerSec)` với `pxPerBeat=42`, `pxPerSec = 42*bpm/60` (cùng tỉ lệ tempo với MIDI). Clip ngắn hiển thị đúng chiều rộng theo tempo (2s@120 → 168px), clip dài scroll; playhead theo tỉ lệ tempo (`t*pxPerSec`, khóa giữa khi scroll). Ruler cùng scale (bỏ stretch `Math.max(w, ...)`). Thêm `audioDuration` vào deps effect redraw.
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/static/js/app.precompiled.js`, `app/templates/index.html`
- **Ghi chú/Test (nếu có):** Probe drawCanvas: 2s@120 → contentW=168, waveform maxX 167.8 < 300 (không giãn); 10s → 840 scroll; 2s@240 → 336 (rộng hơn theo tempo). Hard reload.