汉堡菜单导航项动画

时间:2021-02-26 10:59:16

标签: javascript css animation css-transitions animate.css

https://drive.google.com/file/d/1LCS6Z-oP1rqPbRF7tydgVWZEdCEt_RPP/view?usp=sharing 这是汉堡菜单导航菜单项上的动画效果。 单击汉堡菜单时,每个导航菜单项都会出现动画。
我试图重新创建一个。 https://codepen.io/coral_Sb/pen/VwmQbLo 我不明白我哪里出错了?

每次点击汉堡菜单时都会播放动画。

.nav-menu {
  background-color: red;
}

.nav-menu ul li a {
  color: #fff;
  text-decoration: none;
  margin-bottom: 20px;
}

li:first-child {
  animation: bringback 1s 0s forwards;
}

li:nth-child(2) {
  animation: bringback 1s 2s forwards;
}

.nav-menu li:nth-child(3) {
  animation: bringback 1s 3s forwards;
}

.nav-menu li:nth-child(4) {
  animation: bringback 1s 4s forwards;
}

.nav-menu li:nth-child(5) {
  animation: bringback 1s 5s forwards;
}

.nav-menu li:nth-child(6) {
  animation: bringback 1s 6s forwards;
}

.nav-menu li:nth-child(7) {
  animation: bringback 1s 7s forwards;
}

.nav-menu li:nth-child(8) {
  animation: bringback 1s 8s forwards;
}

.nav-menu li:nth-child(9) {
  animation: bringback 1s 9s forwards;
}

.nav-menu li:nth-child(10) {
  animation: bringback 1s 10s forwards;
}

@keyframes bringback {
  to {
    opacity: 1;
    text-indent: 25px;
  }
}
<div class="nav-menu" id="nav-menu">

  <ul id=" check-ul" style="list-style:none">
    <li>
      <!-- class="active1"-->
      <span><img src="images/birla-logo.png" alt=""></span>
    </li>
    <br>
    <li>
      <a href="#">Home</a>
    </li>
    <li>
      <a href="#">About us <span class="fas fa-sort-down mr-3" style="width: 20px;"></span> </a>
    </li>
    <li>
      <a href="#">Curriculum</a>
    </li>
    <li>
      <a href="#">Criteria</a>
    </li>
    <li>
      <a href="#">Admission Process</a>
    </li>
    <li>
      <a href="#">Careers </a>
    </li>
    <li>
      <a href="#">Contact us </a>
    </li>
    <li>
      <a href="#">Enquire Now </a>
    </li>
  </ul>
</div>

2 个答案:

答案 0 :(得分:1)

不要为任意数量的项 li:nth-child(N) 硬编码 CSS - 很难维护

顺序交错的延迟动画

使用 CSS 变量通过填充模式 both 创建交错动画,并在 CSS calc() 中使用该 CSS 变量控制延迟:

#check-ul li {
  animation: animate 350ms ease calc(var(--i) * 200ms) both;
}

@keyframes animate {
  0% {
    opacity: 0;
    transform: translateX(-2em);
  }
  
  100% {
    opacity: 1;
  }
}
<div class="nav-menu" id="nav-menu">
  <ul id="check-ul">
    <li style="--i:1"><a href="#">Home</a></li>
    <li style="--i:2"><a href="#">About us</a></li>
    <li style="--i:3"><a href="#">Curriculum</a></li>
    <li style="--i:4"><a href="#">Criteria</a></li>
    <li style="--i:5"><a href="#">Admission Process</a></li>
    <li style="--i:6"><a href="#">Careers </a></li>
    <li style="--i:7"><a href="#">Contact us</a></li>
    <li style="--i:8"><a href="#">Enquire Now</a></li>
  </ul>
</div>

通过单击按钮在打开时触发菜单动画:

const toggleTarget = (sel) => {
  const EL_targets = document.querySelectorAll(sel);
  EL_targets.forEach(EL => EL.classList.toggle("is-active"));
};

const EL_toggleButtons = document.querySelectorAll("[data-toggle]");
EL_toggleButtons.forEach(EL => EL.addEventListener("click", (ev) => {
  toggleTarget(ev.currentTarget.dataset.toggle);
}));
#nav-menu {
  position: fixed;
  background: #d00;
  color: #fff;
  top: 0;
  left: 0;
  height: 100vh;
  padding: 20px;
  transition: 0.3s;
  transform: translateX(-100%);
}

#nav-menu.is-active {
  transform: translateX(0%);
}

#nav-menu.is-active li {
  animation: animate 350ms ease calc(var(--i) * 100ms) both;
}

@keyframes animate {
  0% {
    opacity: 0;
    transform: translateX(-2em);
  }
  100% {
    opacity: 1;
  }
}
<button type="button" data-toggle="#nav-menu">OPEN MENU</button>
<div id="nav-menu">
  <button type="button" data-toggle="#nav-menu">CLOSE</button>
  <ul>
    <li style="--i:1"><a href="#">Home</a></li>
    <li style="--i:2"><a href="#">About us</a></li>
    <li style="--i:3"><a href="#">Curriculum</a></li>
    <li style="--i:4"><a href="#">Criteria</a></li>
    <li style="--i:5"><a href="#">Admission Process</a></li>
    <li style="--i:6"><a href="#">Careers </a></li>
    <li style="--i:7"><a href="#">Contact us</a></li>
    <li style="--i:8"><a href="#">Enquire Now</a></li>
  </ul>
</div>

答案 1 :(得分:0)

为了完成一个完整的示例,我认为您需要混合使用一些 JavaScript。

让我们首先创建必要的组件来正确显示视频中的导航来解决这个问题:

<div class="navigation">
  <button id="toggle-button">
  <svg class="menu-button" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
  </svg>
</button>

并相应地设置样式:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  font-family: 'Roboto';
}

#toggle-button {
  background: none;
    color: inherit;
    border: none;
    padding: 0;
    font: inherit;
    cursor: pointer;
    outline: inherit;
}

.navigation {
  background: #1f2937;
}

.menu-button {
  color: white;
  width: 2.3rem;
  height 2.3rem;
}

接下来我们需要为面板、推子和侧边菜单准备必要的标记。

<div class="overlay-container hidden">
    <div class="overlay"></div>
    <div class="panel">
      <ul class="menu">
        <li class="hidden" style="--i:1">Menu item #1</li>
        <li class="hidden" style="--i:2">Menu item #2</li>
        <li class="hidden" style="--i:3">Menu item #3</li>
        <li class="hidden" style="--i:4">Menu item #4</li>
      </ul>
    </div>
  </div>

当然还有风格:

.overlay-container.hidden {
  display: none;
}

.overlay-container {
  overflow: hidden;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.overlay.fade {
  opacity: 0.6;
}

.overlay {
  position: absolute;
  width: 100vw;
  height: 100vh;
  opacity: 0;
  background: black;
  transition: opacity 300ms ease-out;
}

.panel.slide {
  transform: translateX(0%);
}

.panel {
  position: absolute;
  height: 100vh;
  width: 18rem;
  background: #c00136;
  transform: translateX(-100%);
  transition: transform 300ms ease-out;
}

.menu {
  padding: 1rem 1rem;
  list-style-type: none;
}

.menu li.hidden {
  visibility: hidden;
}

.menu li {
  color: #f7f7f7;
  margin: 1rem 0;
}

.menu li.fadeInLeft {
  animation: fadeInLeft 350ms ease calc(var(--i) * 200ms) both;
}

@keyframes fadeInLeft {
  0% {
    opacity: 0;
    transform: translateX(-2em);
  }

  100% {
    opacity: 1;
  }
}

现在使用这一点 javascript,您可以将所有内容编排在一起。请注意我如何使用一些过渡和动画,以便我们可以按顺序计时

let button = document.getElementById("toggle-button");
let backbox = document.querySelectorAll('.overlay-container')[0];
let overlay = document.querySelectorAll('.overlay')[0];
let panel = document.querySelectorAll('.panel')[0];

/*
 * Since transitions from 'hidden'
 * to 'block' don't animate we need 
 * to trigger a browser repaint by
 * asking the element for it's height
 */
function forceRepaint(element) {
  return element.offsetHeight;
}

button.addEventListener("click", function () {
  backbox.classList.remove('hidden');
  forceRepaint(backbox);
  overlay.classList.add('fade');
  panel.classList.add('slide');
});

panel.addEventListener("transitionend", function () {
  document.querySelectorAll('.menu li').forEach(node => {
    node.classList.remove("hidden");
    node.classList.add('fadeInLeft');
  })
});

我建议你慢慢地、循序渐进地解决这些问题,这样你以后也能自己解决这些问题。像这样的问题一开始看起来很复杂,但您必须将它们分解成更小的部分。

最后,这一切是如何结合在一起的。

let button = document.getElementById("toggle-button");
let backbox = document.querySelectorAll('.overlay-container')[0];
let overlay = document.querySelectorAll('.overlay')[0];
let panel = document.querySelectorAll('.panel')[0];

/*
 * Since transitions from 'hidden'
 * to 'block' don't animate we need 
 * to trigger a browser repaint by
 * asking the element for it's height
 */
function forceRepaint(element) {
  return element.offsetHeight;
}

button.addEventListener("click", function() {
  backbox.classList.remove('hidden');
  forceRepaint(backbox);
  overlay.classList.add('fade');
  panel.classList.add('slide');
});

panel.addEventListener("transitionend", function() {
  document.querySelectorAll('.menu li').forEach(node => {
    node.classList.remove("hidden");
    node.classList.add('fadeInLeft');
  })
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  font-family: 'Roboto';
}

#toggle-button {
  background: none;
  color: inherit;
  border: none;
  padding: 0;
  font: inherit;
  cursor: pointer;
  outline: inherit;
}

.navigation {
  background: #1f2937;
}

.menu-button {
  color: white;
  width: 2.3rem;
  height 2.3rem;
}

.overlay-container.hidden {
  display: none;
}

.overlay-container {
  overflow: hidden;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.overlay.fade {
  opacity: 0.6;
}

.overlay {
  position: absolute;
  width: 100vw;
  height: 100vh;
  opacity: 0;
  background: black;
  transition: opacity 300ms ease-out;
}

.panel.slide {
  transform: translateX(0%);
}

.panel {
  position: absolute;
  height: 100vh;
  width: 18rem;
  background: #c00136;
  transform: translateX(-100%);
  transition: transform 300ms ease-out;
}

.menu {
  padding: 1rem 1rem;
  list-style-type: none;
}

.menu li.hidden {
  visibility: hidden;
}

.menu li {
  color: #f7f7f7;
  margin: 1rem 0;
}

.menu li.fadeInLeft {
  animation: fadeInLeft 350ms ease calc(var(--i) * 200ms) both;
}

@keyframes fadeInLeft {
  0% {
    opacity: 0;
    transform: translateX(-2em);
  }
  100% {
    opacity: 1;
  }
}
<div class="navigation">
  <button id="toggle-button">
  <svg class="menu-button" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
  </svg>
  </button>

  <div class="overlay-container hidden">
    <div class="overlay"></div>
    <div class="panel">
      <ul class="menu">
        <li class="hidden" style="--i:1">Menu item #1</li>
        <li class="hidden" style="--i:2">Menu item #2</li>
        <li class="hidden" style="--i:3">Menu item #3</li>
        <li class="hidden" style="--i:4">Menu item #4</li>
      </ul>
    </div>
  </div>
</div>

编辑 我使用 Roko C. Buljan 的回答中的片段来更改我的计时逻辑,因为我是用 javascript 做的,它使示例变得更加简单。