From 186bfc41fbe4501bdfcac7e05f4329b50983d39b Mon Sep 17 00:00:00 2001 From: Seddik Yengui Date: Thu, 12 Dec 2024 14:30:58 +0100 Subject: [PATCH 1/3] Fix: Prevent visual refresh glitches in NAD by applying debounce only during zoom operations Signed-off-by: Seddik Yengui --- .../network-area-diagram-viewer.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/components/network-area-diagram-viewer/network-area-diagram-viewer.ts b/src/components/network-area-diagram-viewer/network-area-diagram-viewer.ts index ff17b69f..2791c799 100644 --- a/src/components/network-area-diagram-viewer/network-area-diagram-viewer.ts +++ b/src/components/network-area-diagram-viewer/network-area-diagram-viewer.ts @@ -254,12 +254,17 @@ export class NetworkAreaDiagramViewer { this.onToggleHoverCallback?.(false, null, '', ''); }); } + + let isZooming = false; + this.svgDraw.on('panStart', function () { + isZooming = true; if (drawnSvg.parentElement != undefined) { drawnSvg.parentElement.style.cursor = 'move'; } }); this.svgDraw.on('panEnd', function () { + isZooming = false; if (drawnSvg.parentElement != undefined) { drawnSvg.parentElement.style.removeProperty('cursor'); } @@ -287,7 +292,7 @@ export class NetworkAreaDiagramViewer { // (we have to do this instead of using panzoom's 'zoom' event to have accurate viewBox updates) const targetNode: SVGSVGElement = this.svgDraw.node; // Callback function to execute when mutations are observed - const observerCallback = (mutationList: MutationRecord[]) => { + const handleViewBoxChange = (mutationList: MutationRecord[]) => { for (const mutation of mutationList) { if (mutation.attributeName === 'viewBox') { this.checkAndUpdateLevelOfDetail(targetNode); @@ -295,10 +300,11 @@ export class NetworkAreaDiagramViewer { } }; - // Create a debounced version of the observer callback to limit the frequency of calls when the 'viewBox' attribute changes, - // particularly during zooming operations, improving performance and avoiding redundant updates. - const debouncedObserverCallback = debounce(observerCallback, 50); - const observer = new MutationObserver(debouncedObserverCallback); + // Determine if the callback should be debounced based on zoom activity. + // Debouncing is applied only during zoom operations to improve performance by reducing redundant updates. + // For other actions, debouncing is avoided to prevent issues such as visible refresh glitches in the NAD when moving nodes. + const observerCallback = isZooming ? debounce(handleViewBoxChange, 50) : handleViewBoxChange; + const observer = new MutationObserver(observerCallback); observer.observe(targetNode, { attributeFilter: ['viewBox'] }); } From 4e2c2c8db08a14bb1dff29df2cc3f9a33ed2a307 Mon Sep 17 00:00:00 2001 From: Seddik Yengui Date: Thu, 12 Dec 2024 15:18:54 +0100 Subject: [PATCH 2/3] fix Signed-off-by: Seddik Yengui --- .../network-area-diagram-viewer.ts | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/components/network-area-diagram-viewer/network-area-diagram-viewer.ts b/src/components/network-area-diagram-viewer/network-area-diagram-viewer.ts index 2791c799..95aff0d1 100644 --- a/src/components/network-area-diagram-viewer/network-area-diagram-viewer.ts +++ b/src/components/network-area-diagram-viewer/network-area-diagram-viewer.ts @@ -73,6 +73,7 @@ export class NetworkAreaDiagramViewer { onSelectNodeCallback: OnSelectNodeCallbackType | null; dynamicCssRules: CSS_RULE[]; onToggleHoverCallback: OnToggleNadHoverCallbackType | null; + isZooming: boolean; constructor( container: HTMLElement, @@ -113,6 +114,7 @@ export class NetworkAreaDiagramViewer { this.onMoveTextNodeCallback = onMoveTextNodeCallback; this.onSelectNodeCallback = onSelectNodeCallback; this.onToggleHoverCallback = onToggleHoverCallback; + this.isZooming = false; } public setWidth(width: number): void { @@ -255,16 +257,12 @@ export class NetworkAreaDiagramViewer { }); } - let isZooming = false; - this.svgDraw.on('panStart', function () { - isZooming = true; if (drawnSvg.parentElement != undefined) { drawnSvg.parentElement.style.cursor = 'move'; } }); this.svgDraw.on('panEnd', function () { - isZooming = false; if (drawnSvg.parentElement != undefined) { drawnSvg.parentElement.style.removeProperty('cursor'); } @@ -303,7 +301,14 @@ export class NetworkAreaDiagramViewer { // Determine if the callback should be debounced based on zoom activity. // Debouncing is applied only during zoom operations to improve performance by reducing redundant updates. // For other actions, debouncing is avoided to prevent issues such as visible refresh glitches in the NAD when moving nodes. - const observerCallback = isZooming ? debounce(handleViewBoxChange, 50) : handleViewBoxChange; + const debouncedHandleViewBoxChange = debounce(handleViewBoxChange, 50); + const observerCallback = (mutationList: MutationRecord[]) => { + if (this.isZooming) { + debouncedHandleViewBoxChange(mutationList); + } else { + handleViewBoxChange(mutationList); + } + }; const observer = new MutationObserver(observerCallback); observer.observe(targetNode, { attributeFilter: ['viewBox'] }); } @@ -336,13 +341,30 @@ export class NetworkAreaDiagramViewer { } private enablePanzoom() { - this.svgDraw?.panZoom({ + const panZoomInstance = this.svgDraw?.panZoom({ panning: true, zoomMin: 0.5 / this.ratio, // maximum zoom OUT ratio (0.5 = at best, the displayed area is twice the SVG's size) zoomMax: 20 * this.ratio, // maximum zoom IN ratio (20 = at best, the displayed area is only 1/20th of the SVG's size) zoomFactor: 0.2, margins: { top: 0, left: 0, right: 0, bottom: 0 }, }); + + // Set zooming state when zooming begins + panZoomInstance?.on('zoom', () => { + this.isZooming = true; // Zooming starts + }); + + // Handle touch-based zoom ending + panZoomInstance?.on('pinchZoomEnd', () => { + this.isZooming = false; // Zooming ends (pinch gesture) + }); + + // Handle mouse-based panning and zoom ending + panZoomInstance?.on('panEnd', () => { + if (this.isZooming) { + this.isZooming = false; // Reset zooming state when interaction ends + } + }); } private disablePanzoom() { From f4930be644d52f86dfe5c7a7ee6bbd2aeb49201f Mon Sep 17 00:00:00 2001 From: Seddik Yengui Date: Thu, 12 Dec 2024 15:21:01 +0100 Subject: [PATCH 3/3] fix Signed-off-by: Seddik Yengui --- .../network-area-diagram-viewer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/network-area-diagram-viewer/network-area-diagram-viewer.ts b/src/components/network-area-diagram-viewer/network-area-diagram-viewer.ts index 95aff0d1..056d82ca 100644 --- a/src/components/network-area-diagram-viewer/network-area-diagram-viewer.ts +++ b/src/components/network-area-diagram-viewer/network-area-diagram-viewer.ts @@ -351,18 +351,18 @@ export class NetworkAreaDiagramViewer { // Set zooming state when zooming begins panZoomInstance?.on('zoom', () => { - this.isZooming = true; // Zooming starts + this.isZooming = true; }); // Handle touch-based zoom ending panZoomInstance?.on('pinchZoomEnd', () => { - this.isZooming = false; // Zooming ends (pinch gesture) + this.isZooming = false; }); // Handle mouse-based panning and zoom ending panZoomInstance?.on('panEnd', () => { if (this.isZooming) { - this.isZooming = false; // Reset zooming state when interaction ends + this.isZooming = false; } }); }