GSAP/SVG 根据活动选项卡设置 x/y 来源,并循环事件侦听器
GSAP/SVG setting x/y origin based on active tab, and looping through event listeners
我正在制作带有扩展选项卡的甜甜圈圈 svg。截至昨晚,扩展选项卡功能齐全,正确的 x/y 转换应用于 mouseenter/mouseleave。 (x/y 对于正确的变换原点在鼠标进入和鼠标离开时都是必不可少的 - 这很难让每个选项卡扩展显示在中心,因为它是一个圆圈)。
今天,我尝试通过创建一个额外的循环来进一步推进该项目,该循环根据活动选项卡索引显示相应的内容。 (这是有效的)。
现在我想更进一步,使当前选项卡保持展开状态,直到将鼠标悬停在另一个选项卡上。现在,事件监听器 mouseleave 在我的鼠标离开选项卡时应用(很明显)。除非将鼠标悬停在另一个选项卡上,否则我该怎么做才能使当前选项卡保持“活动状态”? (而不是 mouseleave?)。我对 JS 仍然相当缺乏经验,如果有人能把我送到正确的方向,我会很满足
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%",
}
);
});
}
});
您必须在此处使用“自定义事件”,而不是使用 mouseout
事件。
是的,您可以创建事件...阅读更多内容 here 并发送它们。这使您可以触发一些特殊的事情,而不会干扰任何其他常规事件的“正常行为”。
下面,我将事件称为“撤回”。耶!也可以随意命名!
函数如下:
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 你会在每个 mouseenter
回调结束时调用它,传递当前悬停的索引(因为那个不应该收回)。
unhover(index);
顺便说一句,关于扩展的工作做得很好(而且很快!)!继续做好工作。 ;)
我正在制作带有扩展选项卡的甜甜圈圈 svg。截至昨晚,扩展选项卡功能齐全,正确的 x/y 转换应用于 mouseenter/mouseleave。 (x/y 对于正确的变换原点在鼠标进入和鼠标离开时都是必不可少的 - 这很难让每个选项卡扩展显示在中心,因为它是一个圆圈)。
今天,我尝试通过创建一个额外的循环来进一步推进该项目,该循环根据活动选项卡索引显示相应的内容。 (这是有效的)。
现在我想更进一步,使当前选项卡保持展开状态,直到将鼠标悬停在另一个选项卡上。现在,事件监听器 mouseleave 在我的鼠标离开选项卡时应用(很明显)。除非将鼠标悬停在另一个选项卡上,否则我该怎么做才能使当前选项卡保持“活动状态”? (而不是 mouseleave?)。我对 JS 仍然相当缺乏经验,如果有人能把我送到正确的方向,我会很满足
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%",
}
);
});
}
});
您必须在此处使用“自定义事件”,而不是使用 mouseout
事件。
是的,您可以创建事件...阅读更多内容 here 并发送它们。这使您可以触发一些特殊的事情,而不会干扰任何其他常规事件的“正常行为”。
下面,我将事件称为“撤回”。耶!也可以随意命名!
函数如下:
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 你会在每个 mouseenter
回调结束时调用它,传递当前悬停的索引(因为那个不应该收回)。
unhover(index);
顺便说一句,关于扩展的工作做得很好(而且很快!)!继续做好工作。 ;)