Browse Source

fix(p5): Resolve zoom sketch blanking on window resize

The zoom sketch canvas would turn blank after the browser window was resized.

The root cause was a race condition between the JavaScript `windowResized` event and the browser's layout rendering. The resize event was triggering the `zoomSketch` to resize its own canvas before its parent container (`#zoom-panel`) had been assigned its new, non-zero dimensions by the layout engine. This resulted in the zoom canvas being recreated with a size of 0x0 pixels.

This commit resolves the issue by:
1.  In `radarSketch.js`, deferring the resize call for the zoom sketch using `setTimeout`. This pushes the execution to the end of the event loop, giving the browser time to update the container's dimensions first.
2.  In `zoomSketch.js`, modifying the `handleResize` function to destroy the old, invalid canvas. The canvas is now correctly recreated with the proper dimensions on the next `updateAndDraw` call (triggered by mouse movement), making the solution robust and independent of specific timings.
refactor/modularize
RUSHIL AMBARISH KADU 7 months ago
parent
commit
cdae44016a
  1. 148
      steps/src/p5/radarSketch.js
  2. 33
      steps/src/p5/zoomSketch.js

148
steps/src/p5/radarSketch.js

@ -142,72 +142,69 @@ export const radarSketch = function (p) {
drawPointCloud(p, frameData.pointCloud, plotScales);
if (!appState.isRawOnlyMode) {
drawRegionsOfInterest(p, frameData, plotScales);
drawTrackMarkers(p, plotScales);
// Draw object trajectories and markers if enabled
// if (toggleVelocity.checked) {
// drawTrackMarkers(p, plotScales);
// }
if (togglePredictedPos.checked) {
for (const track of appState.vizData.tracks) {
const log = track.historyLog.find(
(log) => log.frameIdx === appState.currentFrame + 1
);
if (
log &&
log.predictedPosition &&
log.predictedPosition[0] !== null
) {
const pos = log.predictedPosition;
const x = pos[0] * plotScales.plotScaleX;
const y = pos[1] * plotScales.plotScaleY;
p.push();
p.stroke(255, 0, 0); // Red for predicted
p.strokeWeight(2);
p.line(x - 4, y - 4, x + 4, y + 4);
p.line(x + 4, y - 4, x - 4, y + 4);
p.pop();
}
}
}
drawTrackMarkers(p, plotScales);
if (toggleTracks.checked) {
drawTrajectories(p, plotScales);
if (toggleCovariance.checked) {
// Draw object trajectories and markers if enabled
// if (toggleVelocity.checked) {
// drawTrackMarkers(p, plotScales);
// }
if (togglePredictedPos.checked) {
for (const track of appState.vizData.tracks) {
const log = track.historyLog.find(
(log) => log.frameIdx === appState.currentFrame + 1
);
if (
log &&
log.ellipseRadii &&
typeof log.ellipseAngle !== "undefined"
log.predictedPosition &&
log.predictedPosition[0] !== null
) {
const pos = log.predictedPosition;
if (pos && pos[0] !== null) {
drawCovarianceEllipse(
p,
pos,
log.ellipseRadii,
log.ellipseAngle,
plotScales,
log.isStationary
);
}
const x = pos[0] * plotScales.plotScaleX;
const y = pos[1] * plotScales.plotScaleY;
p.push();
p.stroke(255, 0, 0); // Red for predicted
p.strokeWeight(2);
p.line(x - 4, y - 4, x + 4, y + 4);
p.line(x + 4, y - 4, x - 4, y + 4);
p.pop();
}
}
}
}
// Draw cluster centroids if enabled
if (toggleClusterColor.checked) {
drawClusterCentroids(p, frameData.clusters, plotScales);
}
if (toggleTracks.checked) {
drawTrajectories(p, plotScales);
if (toggleCovariance.checked) {
for (const track of appState.vizData.tracks) {
const log = track.historyLog.find(
(log) => log.frameIdx === appState.currentFrame + 1
);
if (
log &&
log.ellipseRadii &&
typeof log.ellipseAngle !== "undefined"
) {
const pos = log.predictedPosition;
if (pos && pos[0] !== null) {
drawCovarianceEllipse(
p,
pos,
log.ellipseRadii,
log.ellipseAngle,
plotScales,
log.isStationary
);
}
}
}
}
}
// Draw cluster centroids if enabled
if (toggleClusterColor.checked) {
drawClusterCentroids(p, frameData.clusters, plotScales);
}
}
}
p.pop();
@ -309,21 +306,47 @@ export const radarSketch = function (p) {
};
// Handle window resizing event
p.windowResized = function () {
/* p.windowResized = function () {
p.resizeCanvas(canvasContainer.offsetWidth, canvasContainer.offsetHeight);
// BUG FIX 2: Re-create the buffer instead of resizing it
staticBackgroundBuffer = p.createGraphics(p.width, p.height);
// 6. Re-create and re-draw the track legend buffer on resize
trackLegendBuffer = p.createGraphics(100, 100);
p.drawTrackLegendToBuffer();
calculatePlotScales();
drawStaticRegionsToBuffer(p, staticBackgroundBuffer, plotScales);
if (appState.zoomSketchInstance) {
appState.zoomSketchInstance.handleResize();
}
if (appState.vizData) {
p.redraw();
}
};
}; */
// In src/p5/radarSketch.js
p.windowResized = function () {
console.log("radarSketch: windowResized triggered!");
// Immediately resize the elements that we know are stable.
p.resizeCanvas(canvasContainer.offsetWidth, canvasContainer.offsetHeight);
staticBackgroundBuffer = p.createGraphics(p.width, p.height);
trackLegendBuffer = p.createGraphics(120, 120);
p.drawTrackLegendToBuffer();
calculatePlotScales();
drawStaticRegionsToBuffer(p, staticBackgroundBuffer, plotScales);
// Defer the call to destroy the zoom canvas.
if (appState.zoomSketchInstance && appState.isCloseUpMode) {
setTimeout(() => {
console.log("radarSketch: Executing deferred call to zoomSketch.handleResize().");
appState.zoomSketchInstance.handleResize();
}, 10); // A 10ms delay is slightly more robust than 0.
}
if (appState.vizData) {
p.redraw();
}
};
// Function to draw the SNR legend to its buffer
p.drawSnrLegendToBuffer = function (minV, maxV) {
@ -375,17 +398,4 @@ export const radarSketch = function (p) {
b.text("SNR", lx, ly - 10);
b.pop();
};
// Handle window resizing event
p.windowResized = function () {
p.resizeCanvas(canvasContainer.offsetWidth, canvasContainer.offsetHeight);
// BUG FIX 2: Re-create the buffer instead of resizing it
staticBackgroundBuffer = p.createGraphics(p.width, p.height);
trackLegendBuffer = p.createGraphics(120, 120);
p.drawTrackLegendToBuffer();
calculatePlotScales();
// Re-draw the static content to the new buffer
drawStaticRegionsToBuffer(p, staticBackgroundBuffer, plotScales);
if (appState.vizData) p.redraw();
};
};

33
steps/src/p5/zoomSketch.js

@ -284,6 +284,7 @@ export const zoomSketch = function (p) {
appState.zoomFactor = 4; // Set a default zoom factor in the global state
p.setup = function () {
console.log("zoomSketch: Setup function has been called."); //debug
p.noLoop();
};
@ -295,16 +296,29 @@ export const zoomSketch = function (p) {
if (container && container.offsetWidth > 0) {
canvas = p.createCanvas(container.offsetWidth, container.offsetHeight);
canvas.parent(containerId);
console.log(`zoomSketch: Canvas CREATED with dimensions ${p.width}x${p.height}`); // debug
} else {
console.warn("zoomSketch: updateAndDraw called, but container is not ready. Aborting draw."); //debug
return;
}
}
console.log(`zoomSketch: updateAndDraw is running. Canvas dimensions are ${p.width}x${p.height}. Hovered items: ${hoveredItems.length}`); //debug
p.redraw();
};
p.handleResize = function() {
console.log("zoomSketch: handleResize triggered. Destroying old canvas.");
if (canvas) {
canvas.remove(); // p5.js function to properly remove the canvas from the DOM
canvas = null; // Set the internal reference to null
}
// The canvas will be recreated automatically the next time updateAndDraw() is called,
// at which point the container will have its correct, final dimensions.
}
p.draw = function () {
if (!appState.vizData || !canvas) return;
console.log("zoomSketch: Draw function is executing."); //debug
p.background(
document.documentElement.classList.contains("dark")
? p.color(55, 65, 81)
@ -385,9 +399,11 @@ export const zoomSketch = function (p) {
// This code runs *after* the zoom transformations have been popped,
// so it draws directly onto the canvas as a fixed UI element.
p.push();
const titleLabel = document.getElementById('toggle-close-up').parentElement;
const titleText = titleLabel ? titleLabel.textContent.trim() : 'Zoom Mode';
const textColor = document.documentElement.classList.contains("dark") ? 220 : 80;
const titleLabel = document.getElementById("toggle-close-up").parentElement;
const titleText = titleLabel ? titleLabel.textContent.trim() : "Zoom Mode";
const textColor = document.documentElement.classList.contains("dark")
? 220
: 80;
p.fill(textColor);
p.noStroke();
p.textSize(16);
@ -397,7 +413,6 @@ export const zoomSketch = function (p) {
p.pop();
// --- END: DRAW TITLE OVERLAY ---
// --- Draw Crosshairs ---
p.stroke(255, 0, 0, 150);
p.strokeWeight(1.5);
@ -405,12 +420,4 @@ export const zoomSketch = function (p) {
p.line(p.width / 2, p.height / 2 - 15, p.width / 2, p.height / 2 + 15);
};
p.windowResized = function () {
if (canvas) {
const container = document.getElementById(containerId);
if (container) {
p.resizeCanvas(container.offsetWidth, container.offsetHeight);
}
}
};
};
Loading…
Cancel
Save