From 02e9c79ec57d10d539ddadce32c6c53aab44b2ea Mon Sep 17 00:00:00 2001 From: Danil Boldyrev Date: Fri, 2 Feb 2024 01:32:13 +0300 Subject: [PATCH 1/3] Fixed a bug with the cursor size when scrolling When scrolling there is a bug, a gradio bug, because of which a parameter breaks the cursor size and it becomes bigger, so I made a solution that gets rid of this problem --- .../canvas-zoom-and-pan/javascript/zoom.js | 54 +++++++++++++------ 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js b/extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js index b7b03ceae..38937d158 100644 --- a/extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js +++ b/extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js @@ -70,6 +70,12 @@ onUiLoaded(async() => { } } + // // Hack to make the cursor always be the same size + function fixCursorSize(){ + window.scrollBy(0, 1); + } + + // Detect whether the element has a horizontal scroll bar function hasHorizontalScrollbar(element) { return element.scrollWidth > element.clientWidth; @@ -245,7 +251,7 @@ onUiLoaded(async() => { elemData[elemId] = { zoom: 1, panX: 0, - panY: 0 + panY: 0, }; let fullScreenMode = false; @@ -335,7 +341,7 @@ onUiLoaded(async() => { elemData[elemId] = { zoomLevel: 1, panX: 0, - panY: 0 + panY: 0, }; if (isExtension) { @@ -359,6 +365,7 @@ onUiLoaded(async() => { } targetElement.style.width = ""; + fixCursorSize() } // Toggle the zIndex of the target element between two values, allowing it to overlap or be overlapped by other elements @@ -430,6 +437,11 @@ onUiLoaded(async() => { targetElement.style.overflow = "visible"; } + console.log("ZoomUpdated") + + // Hack to make the cursor always be the same size + fixCursorSize() + return newZoomLevel; } @@ -485,6 +497,7 @@ onUiLoaded(async() => { targetElement.style.overflow = "visible"; } + fixCursorSize() if (fullScreenMode) { resetZoom(); fullScreenMode = false; @@ -764,14 +777,18 @@ onUiLoaded(async() => { // This is done because the original cursor is tied to the size of the kanvas, it can not be changed, so I came up with a hack that creates an exact copy that works properly - function copySpecificStyles(sourceElement, targetElement) { - // List of CSS property names that we want to clone. - const stylesToCopy = ['top', 'left', 'width', 'height', "opacity"]; - - // For each style in our list, copy it from sourceElement to targetElement. + function copySpecificStyles(sourceElement, targetElement, zoomLevel = 1) { + const stylesToCopy = ['top', 'left', 'width', 'height']; + stylesToCopy.forEach(styleName => { if (sourceElement.style[styleName]) { - targetElement.style[styleName] = sourceElement.style[styleName]; + // Convert style value to number and multiply by zoomLevel. + let adjustedStyleValue = parseFloat(sourceElement.style[styleName]) / zoomLevel; + + // Set the adjusted style value back to target element's style. + // Important: this will work fine for top and left styles as they are usually in px. + // But be careful with other units like em or % that might need different handling. + targetElement.style[styleName] = `${adjustedStyleValue}px`; } }); } @@ -820,12 +837,22 @@ onUiLoaded(async() => { } const canvasAreaEventsHandler = e => { + + canvasCursors.forEach(cursor => cursor.style.display = "none"); + + paintCursorCopy.style.display = "block"; + eraserCursorCopy.style.display = "block"; + if (!activeCursor) return; const cursorNum = eraseButton.classList.contains("active") ? 1 : 0; - // Update the styles of the currently active cursor - copySpecificStyles(canvasCursors[cursorNum], activeCursor); + if(elemData[elemId].zoomLevel != 1){ + copySpecificStyles(canvasCursors[cursorNum], activeCursor, elemData[elemId].zoomLevel); + } else { + // Update the styles of the currently active cursor + copySpecificStyles(canvasCursors[cursorNum], activeCursor); + } let offsetXAdjusted = e.offsetX; let offsetYAdjusted = e.offsetY; @@ -837,17 +864,15 @@ onUiLoaded(async() => { const canvasAreaLeaveHandler = () => { if (activeCursor) { + activeCursor.style.opacity = 0 activeCursor.style.display = "none"; - // Hide the cursor when mouse leaves. - activeCursor.style.opacity = 0; } }; const canvasAreaEnterHandler = () => { if (activeCursor) { + activeCursor.style.opacity = 1 activeCursor.style.display = "block"; - // Show the cursor when mouse enters. - activeCursor.style.opacity = 1; } }; @@ -860,7 +885,6 @@ onUiLoaded(async() => { // Additional listener for handling zoom or other transformations which might affect visual representation targetElement.addEventListener("wheel", canvasAreaEventsHandler); - } applyZoomAndPan(elementIDs.sketch, false); From 9ccdbe2f84a3c04e9e3f718cef71da2fd4438a6d Mon Sep 17 00:00:00 2001 From: Danil Boldyrev Date: Fri, 2 Feb 2024 01:40:25 +0300 Subject: [PATCH 2/3] fix caused unnecessary borders when the cursor leaves the drawing area --- extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js b/extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js index 38937d158..a3bb28c01 100644 --- a/extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js +++ b/extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js @@ -437,8 +437,6 @@ onUiLoaded(async() => { targetElement.style.overflow = "visible"; } - console.log("ZoomUpdated") - // Hack to make the cursor always be the same size fixCursorSize() @@ -833,16 +831,14 @@ onUiLoaded(async() => { } activeCursor = activeCursorCopy; - activeCursor.style.display = "block"; + // activeCursor.style.display = "none"; + activeCursor.style.position = "absolute" } const canvasAreaEventsHandler = e => { canvasCursors.forEach(cursor => cursor.style.display = "none"); - paintCursorCopy.style.display = "block"; - eraserCursorCopy.style.display = "block"; - if (!activeCursor) return; const cursorNum = eraseButton.classList.contains("active") ? 1 : 0; From 7af009deb5c2e6d2fac35de4b90ffe082c9a00e8 Mon Sep 17 00:00:00 2001 From: Danil Boldyrev Date: Fri, 2 Feb 2024 02:14:54 +0300 Subject: [PATCH 3/3] moved the part of code to a more suitable place, lint --- .../canvas-zoom-and-pan/javascript/zoom.js | 250 +++++++++--------- 1 file changed, 128 insertions(+), 122 deletions(-) diff --git a/extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js b/extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js index a3bb28c01..5a3cff109 100644 --- a/extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js +++ b/extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js @@ -71,10 +71,28 @@ onUiLoaded(async() => { } // // Hack to make the cursor always be the same size - function fixCursorSize(){ + function fixCursorSize() { window.scrollBy(0, 1); } - + + function copySpecificStyles(sourceElement, targetElement, zoomLevel = 1) { + const stylesToCopy = ['top', 'left', 'width', 'height']; + + stylesToCopy.forEach(styleName => { + if (sourceElement.style[styleName]) { + // Convert style value to number and multiply by zoomLevel. + let adjustedStyleValue = parseFloat(sourceElement.style[styleName]) / zoomLevel; + + // Set the adjusted style value back to target element's style. + // Important: this will work fine for top and left styles as they are usually in px. + // But be careful with other units like em or % that might need different handling. + targetElement.style[styleName] = `${adjustedStyleValue}px`; + } + }); + + targetElement.style["opacity"] = sourceElement.style["opacity"]; + } + // Detect whether the element has a horizontal scroll bar function hasHorizontalScrollbar(element) { @@ -253,10 +271,110 @@ onUiLoaded(async() => { panX: 0, panY: 0, }; + let fullScreenMode = false; - // Remove border, cause bags + // Cursor manipulation script for a painting application. + // The purpose of this code is to create custom cursors (for painting and erasing) + // that can change depending on which button the user presses. + // When the mouse moves over the canvas, the appropriate custom cursor also moves, + // replicating its appearance dynamically based on various CSS properties. + + // This is done because the original cursor is tied to the size of the kanvas, it can not be changed, so I came up with a hack that creates an exact copy that works properly + + const eraseButton = targetElement.querySelector(`button[aria-label='Erase button']`); + const paintButton = targetElement.querySelector(`button[aria-label='Draw button']`); + + const canvasCursors = targetElement.querySelectorAll("span.svelte-btgkrd"); + const paintCursorCopy = canvasCursors[0].cloneNode(true); + const eraserCursorCopy = canvasCursors[1].cloneNode(true); + + canvasCursors.forEach(cursor => cursor.style.display = "none"); + + canvasCursors[0].parentNode.insertBefore(paintCursorCopy, canvasCursors[0].nextSibling); + canvasCursors[1].parentNode.insertBefore(eraserCursorCopy, canvasCursors[1].nextSibling); + + + // targetElement.appendChild(paintCursorCopy); + // paintCursorCopy.style.display = "none"; + + // targetElement.appendChild(eraserCursorCopy); + // eraserCursorCopy.style.display = "none"; + + let activeCursor; + + paintButton.addEventListener('click', () => { + activateTool(paintButton, eraseButton, paintCursorCopy); + }); + + eraseButton.addEventListener('click', () => { + activateTool(eraseButton, paintButton, eraserCursorCopy); + }); + + function activateTool(activeButton, inactiveButton, activeCursorCopy) { + activeButton.classList.add("active"); + inactiveButton.classList.remove("active"); + + // canvasCursors.forEach(cursor => cursor.style.display = "none"); + + if (activeCursor) { + activeCursor.style.display = "none"; + } + + activeCursor = activeCursorCopy; + // activeCursor.style.display = "none"; + activeCursor.style.position = "absolute"; + } + + const canvasAreaEventsHandler = e => { + + canvasCursors.forEach(cursor => cursor.style.display = "none"); + + if (!activeCursor) return; + + const cursorNum = eraseButton.classList.contains("active") ? 1 : 0; + + if (elemData[elemId].zoomLevel != 1) { + copySpecificStyles(canvasCursors[cursorNum], activeCursor, elemData[elemId].zoomLevel); + } else { + // Update the styles of the currently active cursor + copySpecificStyles(canvasCursors[cursorNum], activeCursor); + } + + let offsetXAdjusted = e.offsetX; + let offsetYAdjusted = e.offsetY; + + // Position the cursor based on the current mouse coordinates within target element. + activeCursor.style.transform = + `translate(${offsetXAdjusted}px, ${offsetYAdjusted}px)`; + }; + + const canvasAreaLeaveHandler = () => { + if (activeCursor) { + // activeCursor.style.opacity = 0 + activeCursor.style.display = "none"; + } + }; + + const canvasAreaEnterHandler = () => { + if (activeCursor) { + // activeCursor.style.opacity = 1 + activeCursor.style.display = "block"; + } + }; + + const canvasArea = targetElement.querySelector("canvas"); + + // Attach event listeners to the target element and canvas area + targetElement.addEventListener("mousemove", canvasAreaEventsHandler); + canvasArea.addEventListener("mouseout", canvasAreaLeaveHandler); + canvasArea.addEventListener("mouseenter", canvasAreaEnterHandler); + + // Additional listener for handling zoom or other transformations which might affect visual representation + targetElement.addEventListener("wheel", canvasAreaEventsHandler); + + // Remove border, cause bags const canvasBorder = targetElement.querySelector(".border"); canvasBorder.style.display = "none"; @@ -365,7 +483,7 @@ onUiLoaded(async() => { } targetElement.style.width = ""; - fixCursorSize() + fixCursorSize(); } // Toggle the zIndex of the target element between two values, allowing it to overlap or be overlapped by other elements @@ -417,8 +535,12 @@ onUiLoaded(async() => { const fileInput = gradioApp().querySelector( `${elemId} .upload-container input[type="file"][accept="image/*"]` ); + fileInput.addEventListener("click", resetZoom); + // Create clickble area + const inputCanvas = targetElement.querySelector("canvas"); + // Update the zoom level and pan position of the target element based on the values of the zoomLevel, panX and panY variables function updateZoom(newZoomLevel, mouseX, mouseY) { @@ -438,7 +560,7 @@ onUiLoaded(async() => { } // Hack to make the cursor always be the same size - fixCursorSize() + fixCursorSize(); return newZoomLevel; } @@ -495,7 +617,7 @@ onUiLoaded(async() => { targetElement.style.overflow = "visible"; } - fixCursorSize() + fixCursorSize(); if (fullScreenMode) { resetZoom(); fullScreenMode = false; @@ -766,121 +888,6 @@ onUiLoaded(async() => { gradioApp().addEventListener("mousemove", handleMoveByKey); - - // Cursor manipulation script for a painting application. - // The purpose of this code is to create custom cursors (for painting and erasing) - // that can change depending on which button the user presses. - // When the mouse moves over the canvas, the appropriate custom cursor also moves, - // replicating its appearance dynamically based on various CSS properties. - - // This is done because the original cursor is tied to the size of the kanvas, it can not be changed, so I came up with a hack that creates an exact copy that works properly - - function copySpecificStyles(sourceElement, targetElement, zoomLevel = 1) { - const stylesToCopy = ['top', 'left', 'width', 'height']; - - stylesToCopy.forEach(styleName => { - if (sourceElement.style[styleName]) { - // Convert style value to number and multiply by zoomLevel. - let adjustedStyleValue = parseFloat(sourceElement.style[styleName]) / zoomLevel; - - // Set the adjusted style value back to target element's style. - // Important: this will work fine for top and left styles as they are usually in px. - // But be careful with other units like em or % that might need different handling. - targetElement.style[styleName] = `${adjustedStyleValue}px`; - } - }); - } - - const eraseButton = targetElement.querySelector(`button[aria-label='Erase button']`); - const paintButton = targetElement.querySelector(`button[aria-label='Draw button']`); - - const canvasCursors = targetElement.querySelectorAll("span.svelte-btgkrd"); - const paintCursorCopy = canvasCursors[0].cloneNode(true); - const eraserCursorCopy = canvasCursors[1].cloneNode(true); - - canvasCursors.forEach(cursor => cursor.style.display = "none"); - - canvasCursors[0].parentNode.insertBefore(paintCursorCopy, canvasCursors[0].nextSibling); - canvasCursors[1].parentNode.insertBefore(eraserCursorCopy, canvasCursors[1].nextSibling); - - - // targetElement.appendChild(paintCursorCopy); - paintCursorCopy.style.display = "none"; - - // targetElement.appendChild(eraserCursorCopy); - eraserCursorCopy.style.display = "none"; - - let activeCursor; - - paintButton.addEventListener('click', () => { - activateTool(paintButton, eraseButton, paintCursorCopy); - }); - - eraseButton.addEventListener('click', () => { - activateTool(eraseButton, paintButton, eraserCursorCopy); - }); - - function activateTool(activeButton, inactiveButton, activeCursorCopy) { - activeButton.classList.add("active"); - inactiveButton.classList.remove("active"); - - // canvasCursors.forEach(cursor => cursor.style.display = "none"); - - if (activeCursor) { - activeCursor.style.display = "none"; - } - - activeCursor = activeCursorCopy; - // activeCursor.style.display = "none"; - activeCursor.style.position = "absolute" - } - - const canvasAreaEventsHandler = e => { - - canvasCursors.forEach(cursor => cursor.style.display = "none"); - - if (!activeCursor) return; - - const cursorNum = eraseButton.classList.contains("active") ? 1 : 0; - - if(elemData[elemId].zoomLevel != 1){ - copySpecificStyles(canvasCursors[cursorNum], activeCursor, elemData[elemId].zoomLevel); - } else { - // Update the styles of the currently active cursor - copySpecificStyles(canvasCursors[cursorNum], activeCursor); - } - - let offsetXAdjusted = e.offsetX; - let offsetYAdjusted = e.offsetY; - - // Position the cursor based on the current mouse coordinates within target element. - activeCursor.style.transform = - `translate(${offsetXAdjusted}px, ${offsetYAdjusted}px)`; - }; - - const canvasAreaLeaveHandler = () => { - if (activeCursor) { - activeCursor.style.opacity = 0 - activeCursor.style.display = "none"; - } - }; - - const canvasAreaEnterHandler = () => { - if (activeCursor) { - activeCursor.style.opacity = 1 - activeCursor.style.display = "block"; - } - }; - - const canvasArea = targetElement.querySelector("canvas"); - - // Attach event listeners to the target element and canvas area - targetElement.addEventListener("mousemove", canvasAreaEventsHandler); - canvasArea.addEventListener("mouseout", canvasAreaLeaveHandler); - canvasArea.addEventListener("mouseenter", canvasAreaEnterHandler); - - // Additional listener for handling zoom or other transformations which might affect visual representation - targetElement.addEventListener("wheel", canvasAreaEventsHandler); } applyZoomAndPan(elementIDs.sketch, false); @@ -910,7 +917,6 @@ onUiLoaded(async() => { }; window.applyZoomAndPan = applyZoomAndPan; // Only 1 elements, argument elementID, for example applyZoomAndPan("#txt2img_controlnet_ControlNet_input_image") - window.applyZoomAndPanIntegration = applyZoomAndPanIntegration; // for any extension