简体   繁体   中英

GSAP/SVG setting x/y origin based on active tab, and looping through event listeners

I am working on a doughnut circle svg with expanding tabs. As of last night the expanding tabs are fully functional and the correct x/y transform is applied on mouseenter/mouseleave. (the x/y is essential on both mouse enter and mouse leave for proper transform origin - this was difficult to get each tab expansion to appear centered as it is a circle).

Today I have tried going further with the project by creating an additional loop that displays corresponding content based on the active tab index. (This is working).

Now I want to go a step further by making the current tab stay expanded until another tab is hovered over. Right now the eventlistener mouseleave applies when my mouse leaves the tab (obviously). What can I do to keep the current tab "active" unless hovering over another tab? (rather than the mouseleave?). I am still fairly inexperienced with JS, I'll be content if anyone could just send me in the right direction

CodePen

const subTabs = gsap.utils.toArray(".subtab");
const expandTabs = gsap.utils.toArray(".expandtab");

// Timeline set default duration to .025
const tl = gsap.timeline({ defaults: { duration: 0.025 } });

tl.set(expandTabs, {
    opacity: 0,
    scale: 0.5,
    x: "0%",
    y: "0%",
});

// display corresponding content based on active tab
// Set expand tab x/y when inactive
let tabIndex = 1;
    tabExcerpt(tabIndex);


function currentTab(n) {
    tabExcerpt(tabIndex = n);
}

function tabExcerpt(n) {
    let i;
    let expandTab = document.querySelectorAll(".expandtab");
    let tabExcerpts = document.querySelectorAll(".tab-excerpt");

    if (n > tabExcerpts.length) {tabIndex = 1}
    if (n < 1) {tabIndex = tabExcerpts.length}
    for (i = 0; i < tabExcerpts.length; i++) {
        tabExcerpts[i].style.display = "none";
    }
    for (i = 0; i < expandTab.length; i++) {
        // Need to set expand tab to default x/y when not active
        expandTab[i] = (num) => {
            tl.set(expandTab, {
                scale: 0.5,
                opacity: 0,
                x: "25%",
                y: "25%",
            });
        }
    }
    tabExcerpts[tabIndex-1].style.display = "block";
    // expandTab[tabIndex-1].className.baseVal += " active";
}

subTabs.forEach((subTab, index) => {
    let expandTab = expandTabs[index];

    // Event Listener Hover On
    // If index[0]
    if (index === 0) {
        subTabs[0].addEventListener("mouseenter", (event) => {
            console.log("you entered region number " + index);
            tl.fromTo(
                expandTab,
                {
                    scale: 0.5,
                    opacity: 0,
                    x: "30%",
                    y: "25%",
                },
                {
                    scale: 1,
                    opacity: 1,
                    x: "0%",
                    y: "0%",
                }
            );
        });
    } else if (index === 1) {
        subTabs[1].addEventListener("mouseenter", (event) => {
            console.log("you entered region number " + index);
            tl.fromTo(
                expandTab,
                {
                    scale: 0.5,
                    opacity: 0,
                    x: "24%",
                    y: "39%",
                },
                {
                    scale: 1,
                    opacity: 1,
                    x: "0%",
                    y: "0%",
                }
            );
        });
    } else if (index === 2) {
        subTabs[2].addEventListener("mouseenter", (event) => {
            console.log("you entered region number " + index);
            tl.fromTo(
                expandTab,
                {
                    scale: 0.5,
                    opacity: 0,
                    x: "25%",
                    y: "25%",
                },
                {
                    scale: 1,
                    opacity: 1,
                    x: "0%",
                    y: "0%",
                }
            );
        });
    } else if (index === 3) {
        subTabs[3].addEventListener("mouseenter", (event) => {
            console.log("you entered region number " + index);
            tl.fromTo(
                expandTab,
                {
                    scale: 0.5,
                    opacity: 0,
                    x: "25%",
                    y: "25%",
                },
                {
                    scale: 1,
                    opacity: 1,
                    x: "0%",
                    y: "0%",
                }
            );
        });
    } else if (index === 4) {
        subTabs[4].addEventListener("mouseenter", (event) => {
            console.log("you entered region number " + index);
            tl.fromTo(
                expandTab,
                {
                    scale: 0.5,
                    opacity: 0,
                    x: "25%",
                    y: "25%",
                },
                {
                    scale: 1,
                    opacity: 1,
                    x: "0%",
                    y: "0%",
                }
            );
        });
    }

    // Event Listener Hover off
    // if index[0]
    if (index === 0) {
        subTabs[0].addEventListener("mouseleave", (event) => {
            console.log("you exited region number " + index);
            tl.fromTo(
                expandTab,
                {
                    scale: 1,
                    opacity: 1,
                    x: "0%",
                    y: "0%",
                },
                {
                    scale: 0.5,
                    opacity: 0,
                    x: "35%",
                    y: "25%",
                }
            );
        });
    } else if (index === 1) {
        subTabs[1].addEventListener("mouseleave", (event) => {
            console.log("you exited region number " + index);
            tl.fromTo(
                expandTab,
                {
                    scale: 1,
                    opacity: 1,
                    x: "0%",
                    y: "0%",
                },
                {
                    scale: 0.5,
                    opacity: 0,
                    x: "24%",
                    y: "39%",
                }
            );
        });
    } else if (index === 2) {
        subTabs[2].addEventListener("mouseleave", (event) => {
            console.log("you exited region number " + index);
            tl.fromTo(
                expandTab,
                {
                    scale: 1,
                    opacity: 1,
                    x: "0%",
                    y: "0%",
                },
                {
                    scale: 0.5,
                    opacity: 0,
                    x: "25%",
                    y: "25%",
                }
            );
        });
    } else if (index === 3) {
        subTabs[3].addEventListener("mouseleave", (event) => {
            console.log("you exited region number " + index);
            tl.fromTo(
                expandTab,
                {
                    scale: 1,
                    opacity: 1,
                    x: "0%",
                    y: "0%",
                },
                {
                    scale: 0.5,
                    opacity: 0,
                    x: "25%",
                    y: "25%",
                }
            );
        });
    } else if (index === 4) {
        subTabs[4].addEventListener("mouseleave", (event) => {
            console.log("you exited region number " + index);
            tl.fromTo(
                expandTab,
                {
                    scale: 1,
                    opacity: 1,
                    x: "0%",
                    y: "0%",
                },
                {
                    scale: 0.5,
                    opacity: 0,
                    x: "25%",
                    y: "25%",
                }
            );
        });
    }
});

Instead of using the mouseout event here, you will have to use a "custom event".

Yes, you can create events... Read more here and dispatch them. That allows you to trigger something special without interfering with the "normal behavior" of any other regular event.

Below, I called the event "retract". Yay! You also can name it like you wish!

Here is the function:

function unhover(exceptIndex){
  subTabs[exceptIndex].classList.add("expanded")
  subTabs.forEach((subTab, index) => {
    if(index != exceptIndex && subTab.classList.contains("expanded")){
      let event = new Event('retract');
      subTab.dispatchEvent(event);
      subTab.classList.remove("expanded");
    }
  })
}

Andd you will call it at the end of each mouseenter callbacks, passing the index of the currently hovered one (because that one should not retract).

unhover(index);

Here is your CodePen forked and edited

Nice (and fast,) work about the expanding. by the way; Keep on the good job. ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM