简体   繁体   English

如何将响应式导航栏上的菜单图标动画化为 x 图标?

[英]How do I make a menu icon on a responsive navigation bar animated into an x icon?

I am making my first web app, and am working on a top navigation bar.我正在制作我的第一个 Web 应用程序,并且正在开发顶部导航栏。 I am making it responsive, where the menu icon only shows up if the screen width is less than 600 px.我让它响应,菜单图标仅在屏幕宽度小于 600 像素时显示。 I would like for the menu icon to turn into an X icon once the menu icon is clicked on, but I am not quite sure how to do this.一旦单击菜单图标,我希望菜单图标变成 X 图标,但我不太确定如何执行此操作。

Below is my code for the navigation bar.下面是我的导航栏代码。

''' '''

    <!DOCTYPE html>
    <html>
    <head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
    body {margin:0;font-family:"Trebuchet MS"}

    .topnav {
        overflow: hidden;
        background-color: #333;
    }

    .topnav a {
        float: left;
        display: block;
        color: #f2f2f2;
        text-align: center;
        padding: 14px 16px;
        text-decoration: none;
        font-size: 17px;
    }

    .active {
        background-color: #4C00AF;
        color: white;
    }

    .topnav .icon {
        display: none;
    }

    .dropdown {
        float: left;
        overflow: hidden;
    }

    .dropdown .dropbtn {
        font-size: 17px;
        border: none;
        outline: none;
        color: white;
        padding: 14px 16px;
        background-color: inherit;
        font-family: inherit;
        margin: 0;
    }

    .dropdown-content {
        display: none;
        position: absolute;
        background-color: #f9f9f9;
        min-width: 160px;
        box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
        z-index: 1;
    }

    .dropdown-content a {
        float: none;
        color: black;
        padding: 12px 16px;
        text-decoration: none;
        display: block;
        text-align: left;
    }

    .topnav a:hover, .dropdown:hover .dropbtn {
        background-color: #554647;
        color: white;
    }

    .dropdown-content a:hover {
        background-color: #ddd;
        color: black;
    }

    .dropdown:hover .dropdown-content {
        display: block;
    }

    @media screen and (max-width: 600px) {
        .topnav a:not(:first-child), .dropdown .dropbtn {
            display: none;
        }
        .topnav a.icon {
            float: right;
            display: block;
        }
    }

    @media screen and (max-width: 600px) {
        .topnav.responsive {position: relative;}
        .topnav.responsive .icon {
            position: absolute;
            right: 0;
            top: 0;
        }
        .topnav.responsive a {
            float: none;
            display: block;
            text-align: left;
        }
        .topnav.responsive .dropdown {float: none;}
        .topnav.responsive .dropdown-content {position: relative;}
        .topnav.responsive .dropdown .dropbtn {
            display: block;
            width: 100%;
            text-align: left;
        }
    }
</style>

    <div class="topnav" id="myTopnav">
        <a href="#home" class="active">Home</a>
        <a href="#contact">Page2</a>
        <div class="dropdown">
            <button class="dropbtn">About
                <i class="fa fa-caret-down"></i>
            </button>
            <div class="dropdown-content">
                <a href="#">Hello</a>
        <a href="#">Salutations</a>
        <a href="#">Hi</a>
            </div>
        </div>
        <a href="javascript:void(0);" style="font-size:15px;" class="icon" 
    onclick="myFunction()">&#9776;</a>
    </div>


    <script>
        function myFunction() {
            var x = document.getElementById("myTopnav");
            if (x.className === "topnav") {
                x.className += " responsive";
            } else {
                x.className = "topnav";
            }
        }
    </script>

    </body>
    </html>

''' '''

Thank you!谢谢!

This worked for me这对我有用

Theory理论

CSS provides all the necessary animation tools. CSS 提供了所有必要的动画工具。 Basically what's happening is this:基本上发生的事情是这样的:

  • The top and bottom lines must rotate to form the X顶线和底线必须旋转以形成 X
  • The middle line must disappear中线必须消失

The X will be taller an more narrow than the hamburger lines, so: X 会比汉堡线更高更窄,所以:

  • The top and middle lines must move out vertically and to the right to maintain its center顶线和中线必须垂直移出并向右移动以保持其中心

Application应用

 /* Define the shape and color of the hamburger lines */ .navbar-toggler span { display: block; background-color: #4f4f4f; height: 3px; width: 25px; margin-top: 5px; margin-bottom: 5px; position: relative; left: 0; opacity: 1; transition: all 0.35s ease-out; transform-origin: center left; } /* top line needs a little padding */ .navbar-toggler span:nth-child(1) { margin-top: 0.3em; } /** * Animate collapse into X. */ /* top line rotates 45 degrees clockwise and moves up and in a bit to close the center of the X in the center of the button */ .navbar-toggler:not(.collapsed) span:nth-child(1) { transform: translate(15%, -33%) rotate(45deg); } /* center line goes transparent */ .navbar-toggler:not(.collapsed) span:nth-child(2) { opacity: 0; } /* bottom line rotates 45 degrees counter clockwise, in, and down a bit to close the center of the X in the center of the button */ .navbar-toggler:not(.collapsed) span:nth-child(3) { transform: translate(15%, 33%) rotate(-45deg) ; } /** * Animate collapse open into hamburger menu */ /* top line moves back to initial position and rotates back to 0 degrees */ .navbar-toggler span:nth-child(1) { transform: translate(0%, 0%) rotate(0deg) ; } /* middle line goes back to regular color and opacity */ .navbar-toggler span:nth-child(2) { opacity: 1; } /* bottom line goes back to initial position and rotates back to 0 degrees */ .navbar-toggler span:nth-child(3) { transform: translate(0%, 0%) rotate(0deg) ; }
 <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"/> <!-- Bootstrap Navigation --> <nav class="navbar bg-light"> <a class="navbar-toggler collapsed border-0" type="button" data-toggle="collapse" data-target="#collapsingNavbar"> <span> </span> <span> </span> <span> </span> </a> <a class="navbar-brand" href="./"> Brand </a> <div class="collapse navbar-collapse" id="collapsingNavbar"> <ul class="nav navbar-nav"> <li class="nav-item"> <a class="nav-link" href="#">About</a> </li> <li class="nav-item"> <a class="nav-link" href="#">Contact</a> </li> </ul> </div> </nav> <main class="container"> <h1>Content Here</h1> <p>Shrink the viewport if to expose the hamburger menu.</p> </main>

What makes it work是什么让它起作用

Specifically, since the top and bottom lines rotate by 45 degrees to form the X, their center lines take up 70% of the width, so they must move in by 15%.具体来说,由于顶线和底线旋转 45 度以形成 X,因此它们的中心线占宽度的 70%,因此它们必须向内移动 15%。 This can be calculated using pythagorean theorem.这可以使用勾股定理计算。

直角尺寸

As it happens, our hamburger menu is 26x21 px, or 24% wider than it is tall, but the X ends up being 20x20 square when you move the lines into place and you take into account the height of the lines (here defined as 3px).碰巧的是,我们的汉堡菜单是 26x21 像素,或者比高度宽 24%,但是当您将线条移动到位并考虑线条的高度(此处定义为 3px)时,X 最终变成了 20x20 正方形)。

In this particular implementation, we are defining the point of rotation of each line as being the center-left.在这个特定的实现中,我们将每条线的旋转点定义为中左。 This affects how much we move the lines up, since the lines are about 3px tall, they each add about (2.1/2)=1.05px to the height of the X, or about 33% of the height of the X.这会影响我们将线条向上移动的程度,因为线条大约 3px 高,它们每条添加大约 (2.1/2)=1.05px 到 X 的高度,或大约 X 高度的 33%。

Therefore 33% is how much they must move out vertically out so the two lines meet at the center of the X and form a 20x20px square.因此,33% 是它们必须垂直向外移动的量,以便两条线在 X 的中心相遇并形成一个 20x20 像素的正方形。

线条必须像这样移动

Customizing定制

The X will always make a square, so to find out how much to move them by, you just need to know the width and height of your <span> bars and the height of the resulting hamburger icon. X 将始终是一个正方形,因此要确定它们的移动量,您只需要知道<span>条的宽度和高度以及生成的汉堡包图标的高度。

Plug those numbers into this equation:将这些数字代入这个等式:

方程

Or in code:或者在代码中:

const line_width = 26; // px
const line_height = 3; // px
const hamburger_height = 21; // px

const x_width = x_height = 0.8 * line_width;
const line_move_y_percent = 100 * (line_width - x_width) / (2 * line_height)
const line_move_right_percent = 100 * (x_height - hamburger_height) / (2 * line_height)

Code for simple animated menu button简单动画菜单按钮的代码

HTML HTML

<button class="menu-btn" id="menu-icon">
  <div class="btn-line"></div>
</button>

CSS CSS

.menu-btn {
  width: 40px;
  height: 40px;
  background: none;
  border: 0;
}

.menu-btn,
.btn-line {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.btn-line,
.btn-line::before,
.btn-line::after {
  width: 35px;
  height: 5px;
  border-radius: 4px;
  background: white;
  transition: all .5s;
}

.btn-line {
  position: relative;
}

.btn-line::before,
.btn-line::after {
  position: absolute;
  content: '';
  top: -11px;
}

.btn-line::after {
  top: 11px;
}

.close > .btn-line {
  transform: rotate(225deg);
  background: red;
}

.close > .btn-line::before,
.close > .btn-line::after {
  top: 0;
  transform: rotate(90deg);
  background: red;
}

JS JS

const btn = document.getElementById('menu-icon');
btn.addEventListener('click', (e) => {
  e.target.classList.toggle('close');
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM