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

creating a rolling menu: rolling just once

[编辑]

我在 numbtongue 提示后重建我的代码。它现在看起来完全不同,并且工作得很好。除了它只工作一次!滚完一圈,就不再滚了。。。 我有两个功能:一个用于转换,另一个用于替换内容。在'transition'函数中,我选择在要中转的元素上添加类,为这些类添加一些CSS。 当我 运行 我的代码时,似乎一切都很完美,只是没有发生转换。怎么了??

JSFIDDLE : jsfiddle.net/arnaudambro/ode8bowb/2/

[原创]

我正在尝试创建一个 "rolling menu",看起来很像页面右侧来自 this awwwarded website : north-east-venture.com 的那个(根本没有我的广告,只是让你知道我是什么我也提到了,以便更好地理解我面临的问题)。

我正在寻找的是:当有人点击菜单中的一项时,该项直接上升,而在上面的项目将在堆栈下。 我做了一些在这里很管用的东西:

JS Fiddle : jsfiddle.net/arnaudambro/7s6ncxyp/

但是如您所见,没有转换。

这是显示 "working" 转换的代码:

JSFiddle : jsfiddle.net/arnaudambro/xtrvsgor/

为了使转换有效,我不得不在 JS 中注释第 84、153、172 和 174 行。

我尽我所能使过渡在整个菜单中正常工作,但似乎当我 "populate the new menu" 时,每个过渡都被终止了。

我的代码有什么问题?

提示:点击链接会丢失菜单位置(当前将其设置为数组大小 = 5),而应该是其他链接的循环槽(见附件)..

成功! 有一些超时,我成功了。不幸的是,它正在工作但仍然有点不稳定,因为似乎没有其他超时选择。我试图测量重新填充菜单完成其工作所花费的时间,并将其作为 setTimeout 值,但它没有用,时间太短了。 无论如何,它已经很好用了,很好!

/*------------------------------ 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;
}
<body>
  <ul class="menu">
    <li class="item">
      <a href="#" class="item-link">
        <p class="item-content" data-menu-position="0">Item 1</p>
      </a>
    </li>
    <li class="item">
      <a href="#" class="item-link">
        <p class="item-content" data-menu-position="1">Item 2</p>
      </a>
    </li>
    <li class="item">
      <a href="#" class="item-link">
        <p class="item-content" data-menu-position="2">Item 3</p>
      </a>
    </li>
    <li class="item">
      <a href="#" class="item-link">
        <p class="item-content" data-menu-position="3">Item 4</p>
      </a>
    </li>
    <li class="item">
      <a href="#" class="item-link">
        <p class="item-content" data-menu-position="4">Item 5</p>
      </a>
    </li>
    <li class="item">
      <a href="#" class="item-link" style="opacity:0">
        <p class="item-content" data-menu-position="5"></p>
      </a>
    </li>
  </ul>



</body>