首页 > 编程语言 >手风琴效果(附加源码)

手风琴效果(附加源码)

时间:2024-12-12 16:27:36浏览次数:8  
标签:status subMenu 菜单 function 附加 源码 var 手风琴 options

目录

写在开头

上期代码主要实现文字滚动效果,开发久了很多功能都是通过框架组件库来完成,但是如果组件满足不了开发需求,还需要开发人员手动封装组件,专门出这样一期文章,通过原生js实现一些特定功能,功能也比较简单,也是想借助这样一个简单的功能,然后来帮助大家了解我们JavaScript,在前端中的作用,另外也培养下我们的代码思维,那我们本次就通过由简单到复杂循序渐进,这份专栏中我们会带领大家用前端实现手风琴效果、js实现三级联动效果、视频网站中重磅推荐模块、图片放大镜、积分抽奖、拼图、无缝轮播图、图片瀑布流、读心术小游戏等等有趣的小功能,纯前端语言实现,都会陆续带给大家。

功能介绍

手风琴效果,垂直菜单,可内嵌子菜单,可以参考饿了么组件库的NavMenu 导航菜单

涉及功能

首先得有一个动画效果,让菜单展开时页面看起来很顺滑,单独写函数也能实现,但是调用的地方多了就不如封装一个函数,函数但凡封装起来,里面涉及的内容就非常多,这里面动画函数我们就简单写一下。

/**
 * 
 * @param {fn} options 
 * form {number}
 * to {number}
 * totalMS {}
 * duration {}
 * onmove {fn}
 * onend {fn}
 */
function createAnimate(options) {
    var from = options.from; // 起始值
    var to = options.to; // 结束值
    var totalMS = options.totalMS || 1000; // 变化总时间
    var duration = options.duration || 15; // 动画间隔时间
    var times = Math.floor(totalMS / duration); // 变化的次数
    var dis = (to - from) / times; // 每一次变化改变的值
    var curTimes = 0; // 当前变化的次数
    var timerId = setInterval(function () {
      from += dis;
      curTimes++; // 当前变化增加一次
      if (curTimes >= times) {
        // 变化的次数达到了
        from = to; // 变化完成了
        clearInterval(timerId); // 不再变化了
        options.onend && options.onend();
      }
      // 无数的可能性,把form传进去方便后续
      options.onmove && options.onmove(from);
    }, duration);
  }
  

简单来一个小功能测试一下功能


<!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>
  </head>
  <style>
    div{
        font-size: 32px;
        text-decoration: line-through;
        color: #ccc;
    }
  </style>
  <body>
    <div>
        原价:¥
        <span>999.99</span>
    </div>
    <h1>
      活动价:¥
      <span>999.99</span>
    </h1>

    <script src="./index.js"></script>
    <script>
      var span = document.querySelector('h1 span');
      //原价999.99,活动价格99.99
      createAnimate({
        from: 999,//初始价格
        to: 99,//优惠价格
        totalTime: 2000,//变化总时长
        durection: 100,//动画间隔
        onmove: function (n) {
          span.innerHTML = n.toFixed(2);
        },
        onend: function () {
          span.style.color = 'red';
        },
      });
    </script>
  </body>
</html>

页面创建

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>手风琴效果</title>
    <link rel="stylesheet" href="./index.css">
</head>
<body>
    <ul class="menu-container">
        <!-- li.menu*4>(h2{菜单$}+(ul.submenu>li*4>{菜单$})) -->
        <li class="menu">
            <h2>菜单1</h2>
            <ul class="submenu">
                <li>菜单1</li>
                <li>菜单2</li>
                <li>菜单3</li>
                <li>菜单4</li>
            </ul>
        </li>
        <li class="menu">
            <h2>菜单2</h2>
            <ul class="submenu">
                <li>菜单1</li>
                <li>菜单2</li>
                <li>菜单3</li>
                <li>菜单4</li>
            </ul>
        </li>
        <li class="menu">
            <h2>菜单3</h2>
            <ul class="submenu">
                <li>菜单1</li>
                <li>菜单2</li>
                <li>菜单3</li>
                <li>菜单4</li>
            </ul>
        </li>
        <li class="menu">
            <h2>菜单4</h2>
            <ul class="submenu">
                <li>菜单1</li>
                <li>菜单2</li>
                <li>菜单3</li>
                <li>菜单4</li>
            </ul>
        </li>
    </ul>
</body>
</html>

样式设置

.menu-container{
    width: 200px;
    margin: 0 auto;
    line-height: 30px;
}
h2{
    padding: 0;
    margin: 0;
    font-size: 100%;
    font-weight: normal;
}
ul li{
    margin: 0;
    padding: 0;
    list-style: none;
}
.menu-container h2 {
    padding: 0 25px;
    background-color: skyblue;
}
.submenu{
    background-color: aliceblue;
    height: 0;
    overflow: hidden;
    margin: 15px 0;
}

逻辑实现

// 交互
var titles = document.querySelectorAll('.menu h2'); // 获取所有的标题元素
var itemHeight = 30; // 每个子菜单的高度
var totalMS = 300; // 动画播放的总时长

for (var i = 0; i < titles.length; i++) {
  titles[i].onclick = function () {
    // 打开一个菜单,收起其他所有菜单
    var beforeOpened = document.querySelector('.submenu[status=opened]');
    if (beforeOpened) {
      closeSubmenu(beforeOpened);
    }
    toggleSubmenu(this.nextElementSibling);
  };
}

// 打开子菜单
function openSubmenu(subMenu) {
  // 子菜单是有状态(关闭、打开、正在打开)
  // 通过自定义属性status,判定它的状态
  var status = subMenu.getAttribute('status');
  if (status !== 'closed' && status) {
    // 不是关闭状态
    return; // 啥也不干
  }
  subMenu.setAttribute('status', 'playing');
  // 将子菜单的高度从0变到?(子项数量*itemHeight)
  createAnimate({
    from: 0,
    to: itemHeight * subMenu.children.length,
    totalMS: totalMS,
    onmove: function (n) {
      subMenu.style.height = n + 'px';
    },
    onend: function () {
      subMenu.setAttribute('status', 'opened');
    },
  });
}

// test
//var testMenu = document.querySelector('.submenu');

// 关闭子菜单
function closeSubmenu(subMenu) {
  // 子菜单是有状态(关闭、打开、正在播放动画)
  // 通过自定义属性status,判定它的状态
  var status = subMenu.getAttribute('status');

  if (status !== 'opened') {
    // 不是打开状态
    return; // 啥也不干
  }
  subMenu.setAttribute('status', 'playing');
  // 将子菜单的高度从0变到?(子项数量*itemHeight)
  createAnimate({
    from: itemHeight * subMenu.children.length,
    to: 0,
    totalMS: totalMS,
    onmove: function (n) {
      subMenu.style.height = n + 'px';
    },
    onend: function () {
      subMenu.setAttribute('status', 'closed');
    },
  });
}

// 切换子菜单
function toggleSubmenu(subMenu) {
  var status = subMenu.getAttribute('status');
  if (status === 'playing') {
    // 正在打开,播放着动画呢
    return;
  } else if (status === 'opened') {
    closeSubmenu(subMenu);
  } else {
    openSubmenu(subMenu);
  }
}

代码量不多,主要是js部分实现逻辑略有复杂,基本上写出一个打开菜单函数,关闭菜单同理就能写出来。

标签:status,subMenu,菜单,function,附加,源码,var,手风琴,options
From: https://blog.csdn.net/weixin_45840519/article/details/144409506

相关文章

  • SSM游戏角色装备交易系统v584e(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、项目背景随着网络游戏行业的蓬勃发展,游戏角色装备交易已成为游戏中不可或缺的一部分。然而,现有的装备交易系统往往存在交易信息不透明、交易安......
  • SSM在线考试系统y597k--(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、项目背景与意义随着互联网技术的飞速发展,传统考试方式逐渐暴露出诸多不足,如组织成本高、效率低下、资源分配不均等问题。在线考试系统作为一种......
  • 源码编译安装python
    python3configure参数:./configure--prefix=/yourpath/python-3.10.12/\--enable-loadable-sqlite-extensions\--enable-optimizationsmake-j16makeinstallpip3installnotebook使用jupyter需要此参数:--enable-loadable-sqlite-extensions,后续进行make&&ma......
  • SSM在线书城管理系统9w0d7(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、项目背景随着互联网技术的飞速发展,人们的阅读习惯逐渐从线下转移到线上。为了满足广大读者的在线阅读需求,并提升图书管理效率,我们计划开发一款......
  • SSM职业高中排课系统的设计与实现18998(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、研究背景与意义随着现代教育体系的不断发展,职业高中的课程安排变得越来越复杂。传统的人工排课方式已难以满足职业高中的需求,因为它需要考虑到......
  • SSM长春光华学院勤工俭学管理系统71n35--(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、项目背景随着高校教育的普及,越来越多的学生选择在校期间参与勤工俭学活动,以减轻家庭经济负担并积累实践经验。长春光华学院作为一所知名学府,积......
  • ThinkPHP+Uniapp二手车置换平台小程序系统源码
    二手车置换平台小程序系统微信小程序+抖音小程序双端数据同步基于ThinkPHP+Uniapp开发的一款二手车置换平台小程序系统,为买家和卖家提供了一个交流和交易的平台,促进了二手车市场的发展!车辆发布:自主发布车辆信息圈子交流:可以在圈子进行信息交流数据统计:每日的访客数量,留言......
  • 计算机毕业设计 | SpringBoot+vue高校教师科研管理系统(附源码+论文)
    1,绪论1.1研究背景互联网时代不仅仅是通过各种各样的电脑进行网络连接的时代,也包含了移动终端连接互联网进行复杂处理的一些事情。传统的互联网时代一般泛指就是PC端,也就是电脑互联网时代,但是最近几十年,是移动互联网时代,是向下一步互联网时代过度的一个重要时代,下一个互联......
  • 计算机毕业设计 | SpringBoot+vue智能家居管理系统 米家家居管理(附源码+论文)
    1,绪论1.1课题研究背景与现状时代的进步使人们的生活实现了部分自动化,由最初的全手动办公已转向手动+自动相结合的方式。比如各种办公系统、智能电子电器的出现,都为人们生活的享受提供帮助。采用新型的自动化方式可以减少手动的办公时间,增加正确率从而增加人们的幸福指数......
  • Springboot基于springboot和vue的耐思招聘网站的设计与实现96n8j(程序+源码+数据库+调
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表用户,企业招聘者,校园招聘者,个人简历,招聘信息,招聘类型,校园招聘,类型,企业申请,沟通信息,沟通回复,校园申请,校园沟通,回复校园开题报告内容一、项目背景随......