From cdae44016a054fd68fa7672e60a6314e5b49c1d7 Mon Sep 17 00:00:00 2001 From: rakadu1 Date: Tue, 14 Oct 2025 10:47:19 +0530 Subject: [PATCH] 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. --- steps/src/p5/radarSketch.js | 148 +++++++++++++++++++----------------- steps/src/p5/zoomSketch.js | 33 ++++---- 2 files changed, 99 insertions(+), 82 deletions(-) diff --git a/steps/src/p5/radarSketch.js b/steps/src/p5/radarSketch.js index 1d1340d..caf925e 100644 --- a/steps/src/p5/radarSketch.js +++ b/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(); - }; }; diff --git a/steps/src/p5/zoomSketch.js b/steps/src/p5/zoomSketch.js index 6fc6296..161cb5b 100644 --- a/steps/src/p5/zoomSketch.js +++ b/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); - } - } - }; };