js手风琴效果
我用了两种方法来完成手风琴效果,第一种是原生js实现,第二种方法只是模仿手风琴效果,看一下就好,主要还是第一种方法
第一种方法
手风琴需求
手风琴效果就是相当于菜单下拉,鼠标点击哪一个菜单,哪一个菜单的下拉菜单就显示出来。具体的需求就是这样,具体的js见
html和css:
html与css话不多说,直接上代码
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>手风琴效果</title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<ul class="container">
<li class="menu-container">
<p>菜单一</p>
<ul class="menu-ul">
<li>菜单一.1</li>
<li>菜单二.2</li>
<li>菜单三.3</li>
<li>菜单四.4</li>
</ul>
</li>
<li class="menu-container">
<p>菜单二</p>
<ul class="menu-ul">
<li>菜单二.1</li>
<li>菜单二.2</li>
<li>菜单二.3</li>
<li>菜单二.4</li>
</ul>
</li>
<li class="menu-container">
<p>菜单三</p>
<ul class="menu-ul">
<li>菜单三.1</li>
<li>菜单三.2</li>
<li>菜单三.3</li>
<li>菜单三.4</li>
</ul>
</li>
<li class="menu-container">
<p>菜单四</p>
<ul class="menu-ul">
<li>菜单四.1</li>
<li>菜单四.2</li>
<li>菜单四.3</li>
<li>菜单四.4</li>
</ul>
</li>
</ul>
<script src="./index.js"></script>
<script src="./animate.js"></script>
</body>
</html>
css:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 200px;
margin: 0 auto;
margin-top: 40px;
}
.menu-container {
background-color: cadetblue;
margin-top: 30px;
}
li {
list-style: none;
}
p {
/* padding-left: 40px; */
margin-left: 40px;
font-size: 15px;
font-weight: bold;
cursor: pointer;
height: 40px;
line-height: 40px;
}
.menu-ul {
padding-left: 20px;
line-height: 40px;
height: 0px;
overflow: hidden;
background-color: violet;
}
js
animate.js
这个代码我就不多讲了,因为我在js小案例-无缝轮播图中讲过了,不懂得可以去看无缝轮播图。这里不多讲解,直接上代码:
// 动画
function createAnimation(options) {
var form = options.form;
var to = options.to;
var totalTime = options.totalTime || 1000;
var duration = options.duration || 15;
var times = Math.floor(totalTime / duration);
var durationHeight = (to - form) / times;
var curTime = 0;
var timeId = setInterval(function() {
form += durationHeight;
curTime++;
if (curTime >= times) {
form = to;
clearInterval(timeId);
options.onend && options.onend();
}
options.onmove && options.onmove(form);
}, duration);
}
index.js
这是核心,主要讲一下我写的思路以及解决办法。
首先是写打开一个子菜单,直接书写一个函数,调用createAnimation函数,起始值是0,结束值是子菜单的个数乘以一个子菜单的高度,然后再onmove中定义height,然后再定义一个子菜单的状态,以便关闭打开,通过自定义属性来判断它的状态,如果是关闭的,就return啥都不干,否则就是play,然后再onend中写入open,表示子菜单已经打开。
然后开始关闭子菜单方法与打开子菜单一样,只不过起始值变成了打开子菜单的结束值,结束值是打开子菜单的起始值。然后自定义属性样式从open变为close。
最后是切换子菜单和收起其他的子菜单,所以只要判断一下子菜单的状态就行了,正在播放动画运行的就return,啥都不干,等于open的就关闭,反之就打开子菜单。然后就是点击事件的补充,以及收起其他的子菜单。完毕
// 封装document.querySelector()
function $(selector) {
return document.querySelector(selector);
}
// 交互
// 获取到所有的菜单项
var title = document.querySelectorAll('.menu-container p');
// console.log(title);
// 遍历所有的菜单项,分别注册鼠标点击事件
for (var i = 0; i < title.length; i++) {
title[i].onclick = function() {
var click = document.querySelector('.menu-ul[status=opened]');
if (click) {
close(click);
}
switchMenu(this.nextElementSibling);
};
}
// 点击菜单,菜单显示出来
var menu = $('.menu-ul');
var menuHeight = 40;
var totalTime = 20;
function open(menu) {
var status = menu.getAttribute('status');
if (status !== 'closed' && status) {
return;
}
menu.setAttribute('status', 'playing');
createAnimation({
form: 0,
to: menuHeight * menu.children.length,
totalTime: 500,
onmove: function(n) {
menu.style.height = n + 'px';
},
onend: function() {
menu.setAttribute('status', 'opened');
},
});
}
function close(menu) {
var status = menu.getAttribute('status');
if (status !== 'opened') {
return;
}
menu.setAttribute('status', 'playing');
createAnimation({
form: menuHeight * menu.children.length,
to: 0,
totalTime: 500,
onmove: function(n) {
menu.style.height = n + 'px';
},
onend: function() {
menu.setAttribute('status', 'closed');
},
});
}
function switchMenu(menu) {
var status = menu.getAttribute('status');
if (status === 'palying') {
return;
} else if (status === 'opened') {
close(menu);
} else {
open(menu);
}
}
第二种方法
这一种方法是鼠标移动上去就显示子菜单了。所以我不做讲解,直接上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
font-size: 100%;
list-style: none;
}
.menu {
width: 200px;
height: 50px;
background: #409eff;
color: #fff;
line-height: 50px;
margin: 0 auto;
margin-top: 50px;
text-align: center;
cursor: pointer;
position: relative;
}
.sub-menu {
background: #ddebfd;
font-size: 14px;
line-height: 35px;
color: #333;
padding: 10px 0;
position: absolute;
width: 100%;
}
</style>
<style>
.sub-menu {
transform-origin: center top;
transform: scaleY(0);
transition: 0.5s;
}
.menu:hover .sub-menu {
transform: scaleY(1);
}
</style>
</head>
<body>
<div class="menu">
<h2>下拉菜单</h2>
<ul class="sub-menu">
<li>子菜单1</li>
<li>子菜单2</li>
<li>子菜单3</li>
<li>子菜单4</li>
</ul>
</div>
</body>
</html>