创建滚动菜单:只滚动一次

时间:2017-11-02 14:10:24

标签: javascript arrays css-transitions transition

[编辑]

我在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行。

我尽我所能使转换在整个菜单中运行,但似乎当我“填充新菜单”时,每次转换都会被杀死。

我的代码错了什么?

2 个答案:

答案 0 :(得分:1)

提示:点击链接会丢失菜单位置(将其设置为当前数组大小= 5),而应循环播放(参见附件)以获取其他链接.. enter image description here

答案 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;
}