fix: WaveformLane grid now matches TempoTrackLane bar:beat structure, bar:beat always shown on tempo lane
This commit is contained in:
+24
-29
@@ -443,26 +443,28 @@ const WaveformLane = ({
|
||||
const PADDING_LEFT = barDuration; // 1-bar margin on left
|
||||
const tStart = scrollLeftVal / zoom - PADDING_LEFT;
|
||||
const tEnd = (scrollLeftVal + drawWidth) / zoom + PADDING_LEFT;
|
||||
let gridSpacing = 1.0;
|
||||
const firstBeat = Math.floor(tStart / beatDuration) * beatDuration;
|
||||
let snapDivisor = 1;
|
||||
if (snapValue && snapValue !== 'free') {
|
||||
const beatDuration = 60 / parseFloat(bpm || 120);
|
||||
let divisor = 1;
|
||||
if (snapValue === '4') divisor = 4; else if (snapValue === '1') divisor = 1; else if (snapValue === '1/2') divisor = 0.5; else if (snapValue === '1/4') divisor = 0.25; else if (snapValue === '1/8') divisor = 0.125; else if (snapValue === '1/16') divisor = 0.0625; else if (snapValue === '1/32') divisor = 0.03125;
|
||||
gridSpacing = beatDuration * divisor;
|
||||
} else {
|
||||
gridSpacing = 60 / parseFloat(bpm || 120);
|
||||
if (snapValue === '4') snapDivisor = 4; else if (snapValue === '1') snapDivisor = 1; else if (snapValue === '1/2') snapDivisor = 0.5; else if (snapValue === '1/4') snapDivisor = 0.25; else if (snapValue === '1/8') snapDivisor = 0.125; else if (snapValue === '1/16') snapDivisor = 0.0625; else if (snapValue === '1/32') snapDivisor = 0.03125;
|
||||
}
|
||||
let drawSpacing = gridSpacing;
|
||||
while (drawSpacing * zoom < 10) {
|
||||
drawSpacing *= 2;
|
||||
}
|
||||
const firstGridStep = Math.floor(tStart / drawSpacing) * drawSpacing;
|
||||
for (let s = firstGridStep; s <= tEnd; s += drawSpacing) {
|
||||
const localX = (s - tStart) * zoom;
|
||||
for (let t = firstBeat; t <= tEnd; t += beatDuration) {
|
||||
const beatNum = Math.floor(t / beatDuration) + 1;
|
||||
const isBar = beatNum % 4 === 1;
|
||||
const localX = (t - tStart) * zoom;
|
||||
if (localX < -200 || localX > drawWidth + 200) continue;
|
||||
ctx.strokeStyle = isBar ? 'rgba(255, 255, 255, 0.12)' : 'rgba(255, 255, 255, 0.04)';
|
||||
ctx.lineWidth = isBar ? 1.2 : 0.5;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(localX, 0);
|
||||
ctx.lineTo(localX, height);
|
||||
ctx.stroke();
|
||||
if (isBar && zoom >= 2) {
|
||||
ctx.fillStyle = 'rgba(255, 255, 255, 0.15)';
|
||||
ctx.font = 'bold 7px Inter, sans-serif';
|
||||
ctx.textAlign = 'left';
|
||||
ctx.fillText(`${Math.ceil(beatNum / 4)}`, localX + 2, 10);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw waveform lane
|
||||
@@ -1237,22 +1239,10 @@ const TempoTrackLane = ({
|
||||
ctx.fillStyle = 'rgba(255, 255, 255, 0.7)';
|
||||
ctx.font = 'bold 9px Inter, sans-serif';
|
||||
ctx.textAlign = 'left';
|
||||
ctx.fillStyle = 'rgba(255, 255, 255, 0.7)';
|
||||
ctx.font = 'bold 9px Inter, sans-serif';
|
||||
ctx.textAlign = 'left';
|
||||
ctx.fillText(`${Math.ceil(beatNum / 4)}`, localX + 3, 11);
|
||||
} else if (zoom >= 2) {
|
||||
ctx.strokeStyle = 'rgba(255, 255, 255, 0.08)';
|
||||
ctx.lineWidth = 1;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(localX, 0);
|
||||
ctx.lineTo(localX, height);
|
||||
ctx.stroke();
|
||||
if (zoom >= 5) {
|
||||
ctx.fillStyle = 'rgba(255, 255, 255, 0.4)';
|
||||
ctx.font = '8px Inter, sans-serif';
|
||||
ctx.textAlign = 'left';
|
||||
const bar = Math.ceil(beatNum / 4);
|
||||
const beat = ((beatNum - 1) % 4) + 1;
|
||||
ctx.fillText(`${bar}:${beat}`, localX + 2, 9);
|
||||
}
|
||||
} else {
|
||||
ctx.strokeStyle = 'rgba(255, 255, 255, 0.08)';
|
||||
ctx.lineWidth = 1;
|
||||
@@ -1261,6 +1251,11 @@ const TempoTrackLane = ({
|
||||
ctx.lineTo(localX, height);
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.fillStyle = 'rgba(255, 255, 255, 0.35)';
|
||||
ctx.font = '7px Inter, sans-serif';
|
||||
const bar = Math.ceil(beatNum / 4);
|
||||
const beat = ((beatNum - 1) % 4) + 1;
|
||||
ctx.fillText(`${bar}:${beat}`, localX + 2, height - 3);
|
||||
}
|
||||
|
||||
// Draw snap sub-ticks at the bottom
|
||||
|
||||
Reference in New Issue
Block a user