「这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战」
Javascript 一个简单的导航展开和关闭效果的实现
之前在很多大佬的个人博客上发现过非常过酷炫的导航栏,感觉挺有意思的。这篇文章主要是记录一下用Javascript和CSS实现一个简单的导航展开和关闭效果。
一、实现的效果
导航展开前
导航展开后
二、实现的思路
首先可以大致分成两个部分
- 左上角的按钮图标
- 导航内容的打开和关闭
左上角的按钮图标可以通过CSS样式来实现,可以通过不同的样式来控制打开和关闭的状态,在js中添加和移除样式来实现状态的改变。
三、步骤
- html模板
首先是一个container容器,里面的bgbox和bar分别是的导航栏和开关按钮。 导航栏的简单样式就不讲了,主要说一说开关按钮。
<div class="container">
<!-- 导航栏 -->
<div class="bgbox" id="box">
<div class="box1" id="xbox1">
<ul>
<li>
<div class="btn from-left"><a href="#">Home</a></div>
</li>
<li>
<div class="btn from-right"><a href="#">Introduction</a></div>
</li>
<li>
<div class="btn from-middle"><a href="#">Groups</a></div>
</li>
<li>
<div class="btn from-bottom"><a href="#">Projects</a></div>
</li>
<li>
<div class="btn from-right"><a href="#">About</a></div>
</li>
<li>
<div class="btn from-left"><a href="#">Contact</a></div>
</li>
</ul>
</div>
</div>
<!-- 导航栏开关 -->
<div class="bar" onclick="change(this)">
<div class="bar1"></div>
<div class="bar2"></div>
<div class="bar3"></div>
</div>
</div>
- css样式 这里主要是说一下开关按钮的样式实现。总的来说开关按钮是由三个小的盒子组成的,一共有两种样式,分别对应着两种状态。
.bar {
width: 40px;
height: 30px;
left: 30px;
position: absolute;
top: 20px;
}
初始状态: 三个盒子是从上往下,依次水平排列。以为块级元素的特性,所以不需要做什么处理。
.bar1,
.bar2,
.bar3 {
width: 35px;
height: 5px;
background-color: rgb(115, 136, 238);
margin: 6px 0;
transition: 0.4s;
}
打开状态: 按钮从三个水平盒子变成了两个交叉盒子。 这里主要是通过旋转和透明来实现的。
其中第一个和第三个盒子分别设置旋转45度,并水平偏移一定距离,实现交叉的效果。 第二个盒子通过设置透明度来实现隐藏。
这样我们就实现了两种样式的开关按钮。接下来要做的就是控制这两种样式的切换。 其实从css代码中也可以看出,这两种样式的切换是通过给父元素添加类来实现的。这里就涉及到js的操作了。
.change .bar1 {
-webkit-transform: rotate(-45deg) translate(-8px, 6px);
transform: rotate(-45deg) translate(-8px, 6px);
background-color: white;
}
.change .bar2 {
opacity: 0;
}
.change .bar3 {
-webkit-transform: rotate(45deg) translate(-8px, -8px);
transform: rotate(45deg) translate(-8px, -8px);
background-color: white;
}
- javascript部分
这里首先是已经在html中写好了click事件的回调函数,当然也可以用添加事件监听器的方法。
function change(x) {
console.log(x)
console.log(this)
console.log("click")
if (x.classList.contains('change')) {
x.classList.remove('change');
document.getElementById("box").style.width = "0";
document.getElementById("xbox1").style.display = "none";
} else {
x.classList.add('change');
document.getElementById("box").style.width = "100%";
document.getElementById("xbox1").style.display = "block";
}
}
这里要特别注意的是
- 在html中注册事件回调的方法,回调函数中的this是指向window
- 需要在注册回调函数的时候将this作为参数传入,这样就可以在函调函数中通过参数获取到具体的DOM元素。
- 整个导航作为一个组件在具体加入到页面中的时候要考虑好相应的大小,位置和层叠性。一般来说可以通过定位来确定位置(可以基于html标签进行定位),需要设置一个较高的层叠性
完整的代码:
<!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">
<title>lala</title>
<link rel="stylesheet" href="nav.css" type="text/css" />
</head>
<body>
<div class="container">
<!-- 导航栏 -->
<div class="bgbox" id="box">
<div class="box1" id="xbox1">
<ul>
<li>
<div class="btn from-left"><a href="#">Home</a></div>
</li>
<li>
<div class="btn from-right"><a href="#">Introduction</a></div>
</li>
<li>
<div class="btn from-middle"><a href="#">Groups</a></div>
</li>
<li>
<div class="btn from-bottom"><a href="#">Projects</a></div>
</li>
<li>
<div class="btn from-right"><a href="#">About</a></div>
</li>
<li>
<div class="btn from-left"><a href="#">Contact</a></div>
</li>
</ul>
</div>
</div>
<!-- 导航栏开关 -->
<div class="bar" onclick="change(this)">
<div class="bar1"></div>
<div class="bar2"></div>
<div class="bar3"></div>
</div>
</div>
<script>
function change(x) {
console.log(x)
console.log(this)
console.log("click")
if (x.classList.contains('change')) {
x.classList.remove('change');
document.getElementById("box").style.width = "0";
document.getElementById("xbox1").style.display = "none";
} else {
x.classList.add('change');
document.getElementById("box").style.width = "100%";
document.getElementById("xbox1").style.display = "block";
}
}
</script>
</body>
</html>
* {
margin: 0;
padding: 0;
list-style-type: none;
}
body {
padding: 0;
margin: 0;
overflow: hidden;
}
.bgbox {
width: 0;
height: 100vh;
background-color: rgb(58, 132, 175);
display:block;
transition: width 0.5s;
margin: 0 auto;
letter-spacing: 0.6rem;
}
.box1{
width: 28rem;
height: 30rem;
margin: 0 auto;
display:none;
}
.bgbox ul {
height: 100%;
padding-top: 18vh;
line-height: 6vh;
}
.bgbox ul li {
list-style: none;
text-align: center;
height: 3.8rem;
margin-bottom: 0.8rem;
}
.bgbox ul li a{
text-decoration: none;
font-size: 2rem;
display: block;
color: rgb(255, 255, 255);
}
.btn {
position: relative;
padding-top: 0.8rem;
padding-bottom: 1.2rem;
padding-right: 3.1rem;
padding-left: 3.1rem;
margin-bottom: 1rem;
font-size: 1.4rem;
letter-spacing: 0.5rem;
-webkit-transition: all 600ms cubic-bezier(0.77, 0, 0.175, 1);
transition: all 600ms cubic-bezier(0.77, 0, 0.175, 1);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
width:23rem;
height: 1.8rem;
margin: 0 auto;
z-index: 2;
}
.btn:before, .btn:after {
content: '';
position: absolute;
-webkit-transition: inherit;
transition: inherit;
z-index: -1;
}
.bar {
width: 40px;
height: 30px;
left: 30px;
position: absolute;
top: 20px;
}
.bar1,
.bar2,
.bar3 {
width: 35px;
height: 5px;
background-color: rgb(115, 136, 238);
margin: 6px 0;
transition: 0.4s;
}
.change .bar1 {
-webkit-transform: rotate(-45deg) translate(-8px, 6px);
transform: rotate(-45deg) translate(-8px, 6px);
background-color: white;
}
.change .bar2 {
opacity: 0;
}
.change .bar3 {
-webkit-transform: rotate(45deg) translate(-8px, -8px);
transform: rotate(45deg) translate(-8px, -8px);
background-color: white;
}