Commit 1a491783 authored by Danil Boldyrev's avatar Danil Boldyrev
Browse files

Made a function applyZoomAndPan isolated each instance

Isolated each instance of applyZoomAndPan, now if you add another element to the page, they will work correctly
parent dc273f74
Loading
Loading
Loading
Loading
+113 −97
Original line number Diff line number Diff line
// Main

// Helper functions
// Get active tab
function getActiveTab(elements, all = false) {
@@ -18,16 +16,18 @@ function getActiveTab(elements, all = false) {
function getTabId(elements, elementIDs) {
    const activeTab = getActiveTab(elements);
    const tabIdLookup = {
      Sketch: elementIDs.sketch,
        "Sketch": elementIDs.sketch,
        "Inpaint sketch": elementIDs.inpaintSketch,
      Inpaint: elementIDs.inpaint,
        "Inpaint": elementIDs.inpaint
    };
    return tabIdLookup[activeTab.innerText];
}

// Get Active main tab to prevent "Undo" on text2img from being disabled
function getActiveMainTab() {
    const selectedTab = document.querySelector("#tabs .tab-nav button.selected");
    const selectedTab = gradioApp().querySelector(
        "#tabs .tab-nav button.selected"
    );
    return selectedTab;
}

@@ -93,18 +93,20 @@ function createHotkeyConfig(defaultHotkeysConfig, hotkeysConfigOpts) {

    if (!mainTabId) return;

        const mainTab = document.querySelector(mainTabId);
    const mainTab = gradioApp().querySelector(mainTabId);
    const img = mainTab.querySelector("img");
        const imageARPreview = document.querySelector("#imageARPreview");
    const imageARPreview = gradioApp().querySelector("#imageARPreview");

    if (!img || !imageARPreview) return;

    imageARPreview.style.transform = "";
    if (parseFloat(mainTab.style.width) > 865) {
          const transformValues = mainTab.style.transform.match(/[-+]?[0-9]*\.?[0-9]+/g).map(Number);
        const transformValues = mainTab.style.transform
            .match(/[-+]?[0-9]*\.?[0-9]+/g)
            .map(Number);
        const [posX, posY, zoom] = transformValues;

          imageARPreview.style.transformOrigin = "0 0"
        imageARPreview.style.transformOrigin = "0 0";
        imageARPreview.style.transform = `scale(${zoom})`;
    }

@@ -138,18 +140,19 @@ onUiLoaded(async() => {

    let isMoving = false;
    let mouseX, mouseY;
    let activeElement;

    const elementIDs = {
        sketch: "#img2img_sketch",
        inpaint: "#img2maskimg",
        inpaintSketch: "#inpaint_sketch",
        img2imgTabs: "#mode_img2img .tab-nav",
        rangeGroup: "#img2img_column_size",
        rangeGroup: "#img2img_column_size"
    };

    async function getElements() {
        const elements = await Promise.all(
            Object.values(elementIDs).map(id => document.querySelector(id))
            Object.values(elementIDs).map(id => gradioApp().querySelector(id))
        );
        return Object.fromEntries(
            Object.keys(elementIDs).map((key, index) => [key, elements[index]])
@@ -157,13 +160,16 @@ onUiLoaded(async() => {
    }

    const elements = await getElements();
    const elemData = {};

    // Apply functionality to the range inputs
    const rangeInputs = elements.rangeGroup
    ? elements.rangeGroup.querySelectorAll("input")
    : [document.querySelector("#img2img_width input[type='range']"), document.querySelector("#img2img_height input[type='range']")];
    // Apply functionality to the range inputs. Restore redmask and correct for long images.
    const rangeInputs = elements.rangeGroup ? elements.rangeGroup.querySelectorAll("input") :
        [
            gradioApp().querySelector("#img2img_width input[type='range']"),
            gradioApp().querySelector("#img2img_height input[type='range']")
        ];

    rangeInputs.forEach((input) => {
    rangeInputs.forEach(input => {
        if (input) {
            input.addEventListener("input", () => restoreImgRedMask(elements, elementIDs));
        }
@@ -178,7 +184,12 @@ onUiLoaded(async() => {
        }

        targetElement.style.transformOrigin = "0 0";
        let [zoomLevel, panX, panY] = [1, 0, 0];

        elemData[elemId] = {
            zoom: 1,
            panX: 0,
            panY: 0
        };
        let fullScreenMode = false;

        // Create tooltip
@@ -197,7 +208,7 @@ onUiLoaded(async() => {
            const tooltipContent = document.createElement("div");
            tooltipContent.className = "tooltip-content";

            // Add info about hotkets
            // Add info about hotkeys
            const zoomKey = hotkeysConfig.canvas_swap_controls ? "Ctrl" : "Shift";
            const adjustKey = hotkeysConfig.canvas_swap_controls ? "Shift" : "Ctrl";

@@ -205,21 +216,15 @@ onUiLoaded(async() => {
                {key: `${zoomKey} + wheel`, action: "Zoom canvas"},
                {key: `${adjustKey} + wheel`, action: "Adjust brush size"},
                {
                    key: hotkeysConfig.canvas_hotkey_reset.charAt(
                        hotkeysConfig.canvas_hotkey_reset.length - 1
                    ),
                    key: hotkeysConfig.canvas_hotkey_reset.charAt(hotkeysConfig.canvas_hotkey_reset.length - 1),
                    action: "Reset zoom"
                },
                {
                    key: hotkeysConfig.canvas_hotkey_fullscreen.charAt(
                        hotkeysConfig.canvas_hotkey_fullscreen.length - 1
                    ),
                    key: hotkeysConfig.canvas_hotkey_fullscreen.charAt(hotkeysConfig.canvas_hotkey_fullscreen.length - 1),
                    action: "Fullscreen mode"
                },
                {
                    key: hotkeysConfig.canvas_hotkey_move.charAt(
                        hotkeysConfig.canvas_hotkey_move.length - 1
                    ),
                    key: hotkeysConfig.canvas_hotkey_move.charAt(hotkeysConfig.canvas_hotkey_move.length - 1),
                    action: "Move canvas"
                }
            ];
@@ -259,12 +264,14 @@ onUiLoaded(async() => {

        // Reset the zoom level and pan position of the target element to their initial values
        function resetZoom() {
            zoomLevel = 1;
            panX = 0;
            panY = 0;
            elemData[elemId] = {
                zoomLevel: 1,
                panX: 0,
                panY: 0
            };

            fixCanvas();
            targetElement.style.transform = `scale(${zoomLevel}) translate(${panX}px, ${panY}px)`;
            targetElement.style.transform = `scale(${elemData[elemId].zoomLevel}) translate(${elemData[elemId].panX}px, ${elemData[elemId].panY}px)`;

            const canvas = gradioApp().querySelector(
                `${elemId} canvas[key="interface"]`
@@ -342,11 +349,14 @@ onUiLoaded(async() => {
        // 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) {
            newZoomLevel = Math.max(0.5, Math.min(newZoomLevel, 15));
            panX += mouseX - (mouseX * newZoomLevel) / zoomLevel;
            panY += mouseY - (mouseY * newZoomLevel) / zoomLevel;

            elemData[elemId].panX +=
                mouseX - (mouseX * newZoomLevel) / elemData[elemId].zoomLevel;
            elemData[elemId].panY +=
                mouseY - (mouseY * newZoomLevel) / elemData[elemId].zoomLevel;

            targetElement.style.transformOrigin = "0 0";
            targetElement.style.transform = `translate(${panX}px, ${panY}px) scale(${newZoomLevel})`;
            targetElement.style.transform = `translate(${elemData[elemId].panX}px, ${elemData[elemId].panY}px) scale(${newZoomLevel})`;

            toggleOverlap("on");
            return newZoomLevel;
@@ -362,9 +372,9 @@ onUiLoaded(async() => {

                let zoomPosX, zoomPosY;
                let delta = 0.2;
                if (zoomLevel > 7) {
                if (elemData[elemId].zoomLevel > 7) {
                    delta = 0.9;
                } else if (zoomLevel > 2) {
                } else if (elemData[elemId].zoomLevel > 2) {
                    delta = 0.6;
                }

@@ -372,8 +382,9 @@ onUiLoaded(async() => {
                zoomPosY = e.clientY;

                fullScreenMode = false;
                zoomLevel = updateZoom(
                    zoomLevel + (operation === "+" ? delta : -delta),
                elemData[elemId].zoomLevel = updateZoom(
                    elemData[elemId].zoomLevel +
                        (operation === "+" ? delta : -delta),
                    zoomPosX - targetElement.getBoundingClientRect().left,
                    zoomPosY - targetElement.getBoundingClientRect().top
                );
@@ -424,9 +435,9 @@ onUiLoaded(async() => {
            targetElement.style.transform = `translate(${offsetX}px, ${offsetY}px) scale(${scale})`;

            // Update global variables
            zoomLevel = scale;
            panX = offsetX;
            panY = offsetY;
            elemData[elemId].zoomLevel = scale;
            elemData[elemId].panX = offsetX;
            elemData[elemId].panY = offsetY;

            fullScreenMode = false;
            toggleOverlap("off");
@@ -500,9 +511,9 @@ onUiLoaded(async() => {
            targetElement.style.transform = `translate(${offsetX}px, ${offsetY}px) scale(${scale})`;

            // Update global variables
            zoomLevel = scale;
            panX = offsetX;
            panY = offsetY;
            elemData[elemId].zoomLevel = scale;
            elemData[elemId].panX = offsetX;
            elemData[elemId].panY = offsetY;

            fullScreenMode = true;
            toggleOverlap("on");
@@ -538,6 +549,8 @@ onUiLoaded(async() => {
            if (!isKeyDownHandlerAttached) {
                document.addEventListener("keydown", handleKeyDown);
                isKeyDownHandlerAttached = true;

                activeElement = elemId;
            }
        }

@@ -545,6 +558,8 @@ onUiLoaded(async() => {
            if (isKeyDownHandlerAttached) {
                document.removeEventListener("keydown", handleKeyDown);
                isKeyDownHandlerAttached = false;

                activeElement = null;
            }
        }

@@ -601,21 +616,23 @@ onUiLoaded(async() => {

        // Detect zoom level and update the pan speed.
        function updatePanPosition(movementX, movementY) {
            let panSpeed = 1.5;
            let panSpeed = 2;

            if (zoomLevel > 8) {
                panSpeed = 2.5;
            if (elemData[elemId].zoomLevel > 8) {
                panSpeed = 3.5;
            }

            panX = panX + movementX * panSpeed;
            panY = panY + movementY * panSpeed;
            elemData[elemId].panX =
                elemData[elemId].panX + movementX * panSpeed;
            elemData[elemId].panY =
                elemData[elemId].panY + movementY * panSpeed;

            targetElement.style.transform = `translate(${panX}px, ${panY}px) scale(${zoomLevel})`;
            targetElement.style.transform = `translate(${elemData[elemId].panX}px, ${elemData[elemId].panY}px) scale(${elemData[elemId].zoomLevel})`;
            toggleOverlap("on");
        }

        function handleMoveByKey(e) {
            if (isMoving) {
            if (isMoving && elemId === activeElement) {
                updatePanPosition(e.movementX, e.movementY);
                targetElement.style.pointerEvents = "none";
            } else {
@@ -635,7 +652,6 @@ onUiLoaded(async() => {
    applyZoomAndPan(elementIDs.inpaint);
    applyZoomAndPan(elementIDs.inpaintSketch);


    // Make the function global so that other extensions can take advantage of this solution
    window.applyZoomAndPan = applyZoomAndPan;
});