From 7701ceda56c394dc96d824620a63236964dc110f Mon Sep 17 00:00:00 2001 From: Dariusz L Date: Sun, 27 Jul 2025 22:51:37 +0200 Subject: [PATCH] Center canvas viewport on fullscreen toggle Adds logic to adjust the canvas viewport to keep content centered when entering or exiting fullscreen mode. The adjustment calculates the difference in container sizes and updates the viewport position accordingly, improving user experience during fullscreen transitions. --- js/CanvasView.js | 33 ++++++++++++++++++++++++++++++++ src/CanvasView.ts | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/js/CanvasView.js b/js/CanvasView.js index f86e79f..88fc5a1 100644 --- a/js/CanvasView.js +++ b/js/CanvasView.js @@ -734,7 +734,36 @@ async function createCanvasWidget(node, widget, app) { let backdrop = null; let originalParent = null; let isEditorOpen = false; + /** + * Adjusts the viewport to keep the content centered when the container size changes. + * @param rectA The original rectangle. + * @param rectB The new rectangle. + * @param direction Determines whether to apply the adjustment for opening (-1) or closing (1). + */ + const adjustViewportForCentering = (rectA, rectB, direction) => { + if (!rectA || !rectB) + return; + const widthDiff = rectB.width - rectA.width; + const heightDiff = rectB.height - rectA.height; + const adjustX = (widthDiff / 2) / canvas.viewport.zoom; + const adjustY = (heightDiff / 2) / canvas.viewport.zoom; + canvas.viewport.x -= adjustX * direction; + canvas.viewport.y -= adjustY * direction; + const action = direction === 1 ? 'OPENING' : 'CLOSING'; + log.info(`FULLSCREEN ${action} - Viewport adjusted for centering:`, { + widthDiff, heightDiff, adjustX, adjustY, + viewport_after: { x: canvas.viewport.x, y: canvas.viewport.y, zoom: canvas.viewport.zoom } + }); + }; const closeEditor = () => { + // Get fullscreen rect BEFORE removing from DOM + const fullscreenRect = backdrop?.querySelector('.painter-modal-content')?.getBoundingClientRect(); + const currentRect = originalParent?.getBoundingClientRect(); + log.info(`FULLSCREEN CLOSING - Window sizes:`, { + current: { width: currentRect?.width, height: currentRect?.height }, + fullscreen: { width: fullscreenRect?.width, height: fullscreenRect?.height }, + viewport_before: { x: canvas.viewport.x, y: canvas.viewport.y, zoom: canvas.viewport.zoom } + }); if (originalParent && backdrop) { originalParent.appendChild(mainContainer); document.body.removeChild(backdrop); @@ -745,6 +774,7 @@ async function createCanvasWidget(node, widget, app) { // Remove ESC key listener when editor closes document.removeEventListener('keydown', handleEscKey); setTimeout(() => { + adjustViewportForCentering(currentRect, fullscreenRect, -1); canvas.render(); if (node.onResize) { node.onResize(); @@ -781,6 +811,9 @@ async function createCanvasWidget(node, widget, app) { // Add ESC key listener when editor opens document.addEventListener('keydown', handleEscKey); setTimeout(() => { + const originalRect = originalParent.getBoundingClientRect(); + const fullscreenRect = modalContent.getBoundingClientRect(); + adjustViewportForCentering(originalRect, fullscreenRect, 1); canvas.render(); if (node.onResize) { node.onResize(); diff --git a/src/CanvasView.ts b/src/CanvasView.ts index 22caaaa..f834fe2 100644 --- a/src/CanvasView.ts +++ b/src/CanvasView.ts @@ -789,7 +789,42 @@ async function createCanvasWidget(node: ComfyNode, widget: any, app: ComfyApp): let originalParent: HTMLElement | null = null; let isEditorOpen = false; + /** + * Adjusts the viewport to keep the content centered when the container size changes. + * @param rectA The original rectangle. + * @param rectB The new rectangle. + * @param direction Determines whether to apply the adjustment for opening (-1) or closing (1). + */ + const adjustViewportForCentering = (rectA: DOMRect, rectB: DOMRect, direction: 1 | -1) => { + if (!rectA || !rectB) return; + + const widthDiff = rectB.width - rectA.width; + const heightDiff = rectB.height - rectA.height; + + const adjustX = (widthDiff / 2) / canvas.viewport.zoom; + const adjustY = (heightDiff / 2) / canvas.viewport.zoom; + + canvas.viewport.x -= adjustX * direction; + canvas.viewport.y -= adjustY * direction; + + const action = direction === 1 ? 'OPENING' : 'CLOSING'; + log.info(`FULLSCREEN ${action} - Viewport adjusted for centering:`, { + widthDiff, heightDiff, adjustX, adjustY, + viewport_after: { x: canvas.viewport.x, y: canvas.viewport.y, zoom: canvas.viewport.zoom } + }); + } + const closeEditor = () => { + // Get fullscreen rect BEFORE removing from DOM + const fullscreenRect = backdrop?.querySelector('.painter-modal-content')?.getBoundingClientRect(); + const currentRect = originalParent?.getBoundingClientRect(); + + log.info(`FULLSCREEN CLOSING - Window sizes:`, { + current: { width: currentRect?.width, height: currentRect?.height }, + fullscreen: { width: fullscreenRect?.width, height: fullscreenRect?.height }, + viewport_before: { x: canvas.viewport.x, y: canvas.viewport.y, zoom: canvas.viewport.zoom } + }); + if (originalParent && backdrop) { originalParent.appendChild(mainContainer); document.body.removeChild(backdrop); @@ -803,6 +838,12 @@ async function createCanvasWidget(node: ComfyNode, widget: any, app: ComfyApp): document.removeEventListener('keydown', handleEscKey); setTimeout(() => { + // Use the actual canvas container for centering calculation + const currentCanvasContainer = originalParent!.querySelector('.painterCanvasContainer.painter-container') as HTMLElement; + const fullscreenCanvasContainer = backdrop!.querySelector('.painterCanvasContainer.painter-container') as HTMLElement; + const currentRect = currentCanvasContainer.getBoundingClientRect(); + const fullscreenRect = fullscreenCanvasContainer.getBoundingClientRect(); + adjustViewportForCentering(currentRect, fullscreenRect, -1); canvas.render(); if (node.onResize) { node.onResize(); @@ -832,6 +873,7 @@ async function createCanvasWidget(node: ComfyNode, widget: any, app: ComfyApp): return; } + backdrop = $el("div.painter-modal-backdrop") as HTMLDivElement; const modalContent = $el("div.painter-modal-content") as HTMLDivElement; @@ -847,6 +889,12 @@ async function createCanvasWidget(node: ComfyNode, widget: any, app: ComfyApp): document.addEventListener('keydown', handleEscKey); setTimeout(() => { + // Use the actual canvas container for centering calculation + const originalCanvasContainer = originalParent!.querySelector('.painterCanvasContainer.painter-container') as HTMLElement; + const fullscreenCanvasContainer = modalContent.querySelector('.painterCanvasContainer.painter-container') as HTMLElement; + const originalRect = originalCanvasContainer.getBoundingClientRect(); + const fullscreenRect = fullscreenCanvasContainer.getBoundingClientRect(); + adjustViewportForCentering(originalRect, fullscreenRect, 1); canvas.render(); if (node.onResize) { node.onResize();