javaScript小案例------js实现手风琴效果篇

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>
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端志茗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值