Animated hamburger navigation

旧街凉风 提交于 2020-05-29 04:19:11

问题


I'm creating a full page navigation shade for my site so that it's the same across all devices. At the moment I have two buttons, one for when the shade is in view and one for when it isn't. I'm wondering if it would be better to have one button always present so it can be animated? I'd be aiming for something like the squeeze animation here but I'm not sure how I'd go about animating that across the two buttons vs just one - or how you'd create it from scratch.

Here's what I'm working with;

const navButtons = document.querySelectorAll('button.nav-action');
const siteNav = document.querySelector('.site-nav');

function onClick(event) {
  siteNav.classList.toggle('active');
}

navButtons.forEach(button => button.addEventListener('click', onClick));
.site-header {
    height: 80px;
    background-color: #FFFFFF;
    display: inline-flex;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1;
    box-shadow: 0px 0.5px 10px #000000;
}

.site-header-fill {
    height: 80px;
}

.site-logo-container {
    height: 60px;
    margin-left: 20px;
    margin-right: auto;
    margin-top: 10px;
    margin-bottom: 10px;
    display: block;
    float: left;
}

.site-logo {
    height: 60px;
    width: auto;
    float: left;
}

.site-nav-action-container {
    height: 50px;
    width: 50px;
    max-width: 50px;
    margin-left: 10px;
    margin-right: 10px;
    margin-top: 15px;
    margin-bottom: 15px;
    display: block;
    float: right;
    text-align: right;
}

.site-nav {
	height: 100%;
	left: 0px;
	position: fixed;
	top: 0px;
	width: 100%;
	background: #3399ff;
	z-index: 2;
	display: none;
}

.site-nav.active {
    display: block;
}

.site-nav-content {
	width: 20%;
	position: absolute;
	left: 50%;
	top: 50%;
	-webkit-transform: translate(-50%, -50%);
	transform: translate(-50%, -50%);
}

@media only screen and (max-width: 500px) {
.site-nav-content {
    width: auto;
    position: absolute;
    left: 50%;
    top: 50%;
    -webkit-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
}
}

.site-nav-pages {
    text-align:center;
}

.nav-action {
    height: 50px;
    width: 50px;
}
<div class="site-header ">
   <div class="site-logo-container">
      <img class="site-logo" src="https://via.placeholder.com/1000x300" alt="Logo">
   </div>
   <div class="site-nav-action-container">
      <button class="nav-action">
         <p>☰</p>
      </button>
   </div>
</div>
<div class="site-nav">
   <div class="site-nav-action-container">
      <button class="nav-action">
         <p>×</p>
      </button>
   </div>
   <div class="site-nav-content">
      <div class="site-nav-pages">
         <p>Page 1</p>
         <p>Page 2</p>
         <p>Page 3</p>
         <p>Page 4</p>
         <p>Page 5</p>
      </div>
   </div>
</div>

At the moment the shade now functions to be visible or not based on button pressed but I wonder if having one button is the way to go or if placing the icon outside of a button would work best.

Ideally the hamburger would animate as the shade is revealed from the top but I'll work on that once a sensible approach to the button is sorted. Any help would be appreciated because I clearly don't know what I'm doing here.

Thanks in advance.


回答1:


You can use for the ☰ to × effect. You can write all the line labels yourself. the first code snippet is an animation that I use a lot, and the second is the animation that I think you want. I installed both so you can use whatever you want to use.

const navButtons = document.querySelectorAll('button.nav-action');
const siteNav = document.querySelector('.site-nav');

function onClick(event) {
  siteNav.classList.toggle('active');
}

navButtons.forEach(button => button.addEventListener('click', onClick));


const menuIcon = document.querySelector(".menu-icon");
menuIcon.addEventListener("click", () => {
  menuIcon.classList.toggle("toggle")
  siteNav.classList.toggle('active');
})
.site-header {
  height: 80px;
  background-color: #FFFFFF;
  display: inline-flex;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  box-shadow: 0px 0.5px 10px #000000;
}

.site-header-fill {
  height: 80px;
}

.site-logo-container {
  height: 60px;
  margin-left: 20px;
  margin-right: auto;
  margin-top: 10px;
  margin-bottom: 10px;
  display: block;
  float: left;
}

.site-logo {
  height: 60px;
  width: auto;
  float: left;
}

.site-nav-action-container {
  height: 50px;
  width: 50px;
  max-width: 50px;
  margin-left: 10px;
  margin-right: 10px;
  margin-top: 15px;
  margin-bottom: 15px;
  display: block;
  float: right;
  text-align: right;
}

.site-nav {
  height: 100%;
  left: 0px;
  position: fixed;
  top: 0px;
  width: 100%;
  background: #3399ff;
  display: none;
}

.site-nav.active {
  display: block;
}

.site-nav-content {
  width: 20%;
  position: absolute;
  left: 50%;
  top: 50%;
  -webkit-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

@media only screen and (max-width: 500px) {
  .site-nav-content {
    width: auto;
    position: absolute;
    left: 50%;
    top: 50%;
    -webkit-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
  }
}

.site-nav-pages {
  text-align: center;
}


/* Menu icon */

.menu-icon {
  cursor: pointer;
  position: absolute;
  z-index: 1;
}

.menu-icon div {
  width: 25px;
  height: 3px;
  background-color: black;
  margin: 5px;
  transition: all .4s ease;
}

.toggle .line1 {
  transform: rotate(-45deg) translate(-5px, 6px);
}

.toggle .line2 {
  opacity: 0;
}

.toggle .line3 {
  transform: rotate(45deg) translate(-5px, -6px);
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
  <title>Document</title>



</head>

<body>

  <div class="site-header ">
    <div class="site-logo-container">
      <img class="site-logo" src="https://via.placeholder.com/1000x300" alt="Logo">
    </div>
    <div class="site-nav-action-container">
      <!-- Menu icon -->
      <div class="menu-icon">
        <div class="line1"></div>
        <div class="line2"></div>
        <div class="line3"></div>
      </div>
    </div>
    <div class="site-nav">
      <div class="site-nav-content">
        <div class="site-nav-pages">
          <p>Page 1</p>
          <p>Page 2</p>
          <p>Page 3</p>
          <p>Page 4</p>
          <p>Page 5</p>
        </div>
      </div>
    </div>



</body>

</html>

const navButtons = document.querySelectorAll('button.nav-action');
const siteNav = document.querySelector('.site-nav');

function onClick(event) {
  siteNav.classList.toggle('active');
}

navButtons.forEach(button => button.addEventListener('click', onClick));

let icon = document.getElementById("nav-icon");
icon.addEventListener("click", () => {
  icon.classList.toggle("open")
  siteNav.classList.toggle('active');

})
.site-header {
  height: 80px;
  background-color: #FFFFFF;
  display: inline-flex;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  box-shadow: 0px 0.5px 10px #000000;
}

.site-header-fill {
  height: 80px;
}

.site-logo-container {
  height: 60px;
  margin-left: 20px;
  margin-right: auto;
  margin-top: 10px;
  margin-bottom: 10px;
  display: block;
  float: left;
}

.site-logo {
  height: 60px;
  width: auto;
  float: left;
}

.site-nav-action-container {
  height: 50px;
  width: 50px;
  max-width: 50px;
  margin-left: 10px;
  margin-right: 10px;
  margin-top: 15px;
  margin-bottom: 15px;
  display: block;
  float: right;
  text-align: right;
}

.site-nav {
  height: 100%;
  left: 0px;
  position: fixed;
  top: 0px;
  width: 100%;
  background: #3399ff;
  display: none;
}

.site-nav.active {
  display: block;
}

.site-nav-content {
  width: 20%;
  position: absolute;
  left: 50%;
  top: 50%;
  -webkit-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

@media only screen and (max-width: 500px) {
  .site-nav-content {
    width: auto;
    position: absolute;
    left: 50%;
    top: 50%;
    -webkit-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
  }
}

.site-nav-pages {
  text-align: center;
}


/* NAV ICON */

#nav-icon span:nth-child(1) {
  top: 0px;
}

#nav-icon span:nth-child(2),
#nav-icon span:nth-child(3) {
  top: 8px;
}

#nav-icon span:nth-child(4) {
  top: 16px;
}

#nav-icon.open span:nth-child(1) {
  top: 18px;
  width: 0%;
  left: 50%;
}

#nav-icon.open span:nth-child(2) {
  transform: rotate(45deg);
}

#nav-icon.open span:nth-child(3) {
  transform: rotate(-45deg);
}

#nav-icon.open span:nth-child(4) {
  top: 18px;
  width: 0%;
  left: 50%;
}

#nav-icon {
  width: 30px;
  height: 25px;
  position: absolute;
  transform: rotate(0deg);
  transition: .5s ease-in-out;
  cursor: pointer;
  z-index: 1;
  top: 30px;
}

#nav-icon span {
  display: block;
  position: absolute;
  height: 3px;
  width: 100%;
  background: #000;
  opacity: 1;
  left: 0;
  transform: rotate(0deg);
  transition: .25s ease-in-out;
}
<div class="site-header ">
  <div class="site-logo-container">
    <img class="site-logo" src="https://via.placeholder.com/1000x300" alt="Logo">
  </div>
  <div class="site-nav-action-container">
    <!-- Menu icon -->
    <div id="nav-icon">
      <span></span>
      <span></span>
      <span></span>
      <span></span>
    </div>
  </div>
  <div class="site-nav">
    <div class="site-nav-content">
      <div class="site-nav-pages">
        <p>Page 1</p>
        <p>Page 2</p>
        <p>Page 3</p>
        <p>Page 4</p>
        <p>Page 5</p>
      </div>
    </div>
  </div>


来源:https://stackoverflow.com/questions/61962735/animated-hamburger-navigation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!