[编辑]
我在numbtongue提示之后重建了我的代码。它现在看起来完全不同,并且运作良好。除了它只工作一次!一次滚动后,它不再滚动...... 我有两个功能:一个用于转换,另一个用于替换内容。在'transition'函数中,我选择向要传输的元素添加类,并为这些类添加一些CSS。 当我运行我的代码时,似乎一切都完美无缺,除了转换不会发生。怎么了?
JSFIDDLE:jsfiddle.net/arnaudambro/ode8bowb/2 /
[原稿]
我正在尝试创建一个“滚动菜单”,看起来非常像this awwwarded网站上的那个:north-east-venture.com位于页面右侧(根本不适合我的广告)要知道我所指的是什么,以便更好地理解我所面临的问题。)
我正在寻找的是:当有人点击菜单中的一个项目时,此项目直接向上,并且上面的项目将在堆栈下面。 我做了一些在这里工作的东西:
JS小提琴:jsfiddle.net/arnaudambro/7s6ncxyp /
但正如你所看到的,没有过渡。
以下是显示“工作”转换的代码:
JSFiddle:jsfiddle.net/arnaudambro/xtrvsgor /
为了使转换工作,我不得不在JS中注释第84,153,172和174行。
我尽我所能使转换在整个菜单中运行,但似乎当我“填充新菜单”时,每次转换都会被杀死。
我的代码错了什么?
答案 0 :(得分:1)
答案 1 :(得分:1)
成功! 有一些超时,我做了伎俩。不幸的是,它工作但仍然有点生涩,因为似乎没有其他选择超时。我试图测量重新填充菜单以完成其工作所花费的时间,并将其作为setTimeout值,但它不起作用,时间太短。 无论如何,它已经很好用了,很好!
OnClickListener
/*------------------------------ Variables -----------------------------------*/
const menu = document.querySelector('.menu');
const items = [...document.querySelectorAll('.item')];
const itemsLink = [...document.querySelectorAll('.item-link')];
const itemsContent = [...document.querySelectorAll('.item-content')];
let translateYHeight = itemsLink[0].offsetHeight;
console.log(translateYHeight)
let textContentItemAtTheTopOfTheStack;
let transitionInSeconds;
let transitionInMilliSeconds;
let clickedItemIndex;
/*--------------------------- Functions - callbacks --------------------------*/
//Get the index. Called in the STEP 1.
function getTheIndexOfTheClickedItem(e) {
//Variable
let clicked;
//We select the <p> only
if (e.target.tagName == "LI") {
clicked = e.target.firstElementChild.firstElementChild;
} else if (e.target.tagName == "A") {
clicked = e.target.firstElementChild;
} else if (e.target.tagName == "P") {
clicked = e.target;
} else {
return false;
}
//Nothing happen if we clicked on the first item
if (clickedItemIndex === 0) {
return;
}
//We get the index of the clicked item
clickedItemIndex = items.indexOf(clicked.parentElement.parentElement);
//We get the textContent of the clicked item, so that when the textContent
//of the first item in the menu is the proper textContent, we are done
textContentItemAtTheTopOfTheStack = itemsContent[clickedItemIndex].textContent;
//We set the total transition time to 1 second
transitionInSeconds = 1 / clickedItemIndex;
transitionInMilliSeconds = transitionInSeconds * 1000;
translateAndFade();
}
/*--------------------------- STEP 1 --------------------------*/
function translateAndFade() {
//We put the proper transition depending on when the translateAndFade function
//is called
let transitionStyle;
if (clickedItemIndex === 1) {
transitionStyle = 'ease-in-out';
} else if (itemsLink[1].textContent.trim() === textContentItemAtTheTopOfTheStack) {
transitionStyle = 'ease-out';
} else if (itemsLink[clickedItemIndex].textContent.trim() === textContentItemAtTheTopOfTheStack) {
transitionStyle = 'ease-in';
} else {
transitionStyle = 'linear';
}
//We add the transitions and fadings we want
itemsLink.forEach(link => {
if (itemsLink.indexOf(link) === 0) {
//We add the fade-out for the first menu-item
link.style.opacity = 0;
link.style.transform = `translateY(-${translateYHeight}px)`;
link.style.transition = `all ${transitionInSeconds}s ${transitionStyle}`;
} else if (itemsLink.indexOf(link) === (itemsLink.length - 1)) {
//We add the fade-in for the last menu-item
link.firstElementChild.textContent = itemsLink[0].textContent.trim();
link.style.opacity = 1;
link.style.transform = `translateY(-${translateYHeight}px)`;
link.style.transition = `all ${transitionInSeconds}s ${transitionStyle}`;
} else {
//We translate every menu-item one step up
link.style.transform = `translateY(-${translateYHeight}px)`;
link.style.transition = `all ${transitionInSeconds}s ${transitionStyle}`;
}
});
//We call repopulateMenu, to repopulate the menu, with enough timeout to
//let the transition happening
window.setTimeout(repopulateMenu, transitionInMilliSeconds);
}
/*--------------------------- STEP 2 --------------------------*/
function repopulateMenu() {
//We remove the transitions
itemsLink.forEach(link => {
if (itemsLink.indexOf(link) === 0) {
//We remove the fade-out for the first menu-item
link.style.opacity = 1;
link.style.transform = ``;
link.style.transition = ``;
} else if (itemsLink.indexOf(link) === (itemsLink.length - 1)) {
//We remove the fade-in for the last menu-item
link.style.opacity = 0;
link.style.transform = ``;
link.style.transition = ``;
} else {
//We remove the translation of all of them
link.style.transform = ``;
link.style.transition = ``;
}
});
//We update the textContents
itemsContent.forEach(item => {
// We put back emptiness for the last menu-item
if (itemsContent.indexOf(item) === (itemsContent.length - 1)) {
item.textContent = '';
} else {
//We replace the content of the item by the one below it
item.textContent = itemsContent[itemsContent.indexOf(item) + 1].textContent.trim();
}
});
//We do all again until the proper item-menu is on top of the stack.
if (itemsContent[0].textContent != textContentItemAtTheTopOfTheStack) {
window.setTimeout(translateAndFade, 20);
} else {
return;
}
}
/*--------------------------- Event listeners --------------------------------*/
menu.addEventListener('click', getTheIndexOfTheClickedItem);
html,
body {
font-family: sans-serif;
font-weight: 100;
color: rgba(41, 44, 45, 1.00);
}
.menu {
margin-top: 50px;
margin-left: 50px;
list-style: none;
/*border: 1px solid #000;*/
}
.transition-translateY {
transition: all 1s;
transform: translateY(-44px);
}
.transition-fadeIn {
transition: all 1s;
transform: translateY(-44px);
opacity: 1;
}
.transition-fadeOut {
transition: all 1s;
transform: translateY(-44px);
opacity: 0;
}
.item {
padding-top: 2px;
padding-bottom: 2px;
font-size: 0.75em;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
text-align: left;
/*border: 1px solid #000;*/
}
.item-link,
.item-link:hover {
height: 25px;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
text-decoration: none;
color: inherit;
}