html自定义垂直导航菜单(目前只支持上级+下级两级菜单)
由于工作的需要,昨天花了三个多小时的事件整理了一份关于垂直导航二级菜单,可以通过js配置的方式初始化菜单box(测试环境:chrome 49、IE 10、IE edge)。
no pic u say a j8? 好吧,先上效果图(由于下面是gif,所以一帧一帧的感觉不流畅。讲道理,事实上,切换非常流畅,自行下载看Demo)。
js配置方式:
配置menuBox的方式:menuBox.init(config);
这里的config有三个属性:
menuBoxId(必需,你要配置的菜单根节点所在元素的Id)
multiple(可选,是否可以同时打开多个上级菜单,默认是false,也就是最多显示一个上级菜单的子菜单)
openIndex(可选,初始化要打开上级菜单的index数组,如果你要传值,按照格式应该是数字数组)
//配置第一个手风琴的基本参数
var config01 = {
//配置菜单的MenuBoxId
menuBoxId: "#menuBox01", //是否可以打开多个上级菜单的子菜单 multiple: false, //初始化打开的 openIndex: [3, 4, 5] } menuBox.init(config01);
然后看下两个菜单Box的配置:
第一个菜单Box:可以同时打开多个上级菜单,初始化的时候打开第0、1个。
//配置第一个手风琴的基本参数 var config01 = { //配置菜单的MenuBoxId menuBoxId: "#menuBox01", //是否可以打开多个二级菜单 multiple: true, //初始化打开的 openIndex: [0,1] } menuBox.init(config01);
第二个菜单Box:不可以打开多个上级菜单,初始化的时候打开第1个,如果传入数组有多个值,默认打开第一个有效的index上级菜单。 //配置第二个手风琴的基本参数 var config02 = { //配置菜单的MenuBoxId menuBoxId: "#menuBox02", //是否可以打开多个二级菜单 multiple: false, //初始化打开的 openIndex: [-1, 1] } menuBox.init(config02);
用到的知识点:
1、flexbox(在ie9及以下布局不兼容,但是还是可以正常看到切换效果)。
2、css3 transform配合transition实现箭头的旋转切换。
3、打开菜单:$().slideDown()、关闭菜单:$().slideUp()、切换菜单:$().slideToggle()。有时间我会修改为css3动画实现切换,尽量不用jquery。
4、<i>标签引用图标font-awesome
下面是相关代码:
html:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="font-awesome/css/font-awesome.css" /> <link rel="stylesheet" href="css/menuBox.css" /> <script type="text/javascript" src="js/jquery-2.2.2.min.js"></script> <script type="text/javascript" src="js/menuBox.js"></script> <title>MenuBox</title> </head> <style> .top { background: lightblue; min-height: 55px; } </style> <body> <div id="top" class="top"> <span> var config01 = {<br> menuBoxId: "#menuBox01",<br> multiple: true,<br> openIndex: [0,1]<br> }<br> menuBox.init(config01);<br><br> var config02 = {<br> menuBoxId: "#menuBox02",<br> multiple: false,<br> openIndex: [-1, 1]<br> }<br> menuBox.init(config02);<br> </span> </div> <div id="leftNav" class="left-nav"> <!-- 作者:15934179313@163.com 时间:2016-08-03 描述:第一个手风琴二级菜单 --> <div id="menuBox01" class="menuBox"> <ul class="spMenuBox"> <li class="spMenuItem"> <div class="spMenu"> <i class="fa fa-chrome"></i> <span>菜单1</span> <i class="fa fa-2x fa-angle-down"></i> </div> <ul class="subMenuBox"> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> </ul> </li> <li class="spMenuItem"> <div class="spMenu"> <i class="fa fa-chrome"></i> <span>菜单1</span> <i class="fa fa-2x fa-angle-down"></i> </div> <ul class="subMenuBox"> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> </ul> </li> <li class="spMenuItem"> <div class="spMenu"> <i class="fa fa-chrome"></i> <span>菜单1</span> <i class="fa fa-2x fa-angle-down"></i> </div> <ul class="subMenuBox"> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> </ul> </li> <li class="spMenuItem"> <div class="spMenu"> <i class="fa fa-chrome"></i> <span>菜单1</span> <i class="fa fa-2x fa-angle-down"></i> </div> <ul class="subMenuBox"> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> </ul> </li> <li class="spMenuItem"> <div class="spMenu"> <i class="fa fa-chrome"></i> <span>菜单1</span> <i class="fa fa-2x fa-angle-down"></i> </div> <ul class="subMenuBox"> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> </ul> </li> <li class="spMenuItem"> <div class="spMenu"> <i class="fa fa-chrome"></i> <span>菜单1</span> <i class="fa fa-2x fa-angle-down"></i> </div> <ul class="subMenuBox"> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> </ul> </li> <li class="spMenuItem"> <div class="spMenu"> <i class="fa fa-chrome"></i> <span>菜单1</span> <i class="fa fa-2x fa-angle-down"></i> </div> <ul class="subMenuBox"> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> </ul> </li> <li class="spMenuItem"> <div class="spMenu"> <i class="fa fa-chrome"></i> <span>菜单1</span> <i class="fa fa-2x fa-angle-down"></i> </div> <ul class="subMenuBox"> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> </ul> </li> <li class="spMenuItem"> <div class="spMenu"> <i class="fa fa-chrome"></i> <span>菜单1</span> <i class="fa fa-2x fa-angle-down"></i> </div> <ul class="subMenuBox"> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> </ul> </li> <li class="spMenuItem"> <div class="spMenu"> <i class="fa fa-chrome"></i> <span>菜单1</span> <i class="fa fa-2x fa-angle-down"></i> </div> <ul class="subMenuBox"> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> </ul> </li> <li class="spMenuItem"> <div class="spMenu"> <i class="fa fa-chrome"></i> <span>菜单1</span> <i class="fa fa-2x fa-angle-down"></i> </div> <ul class="subMenuBox"> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> </ul> </li> <li class="spMenuItem"> <div class="spMenu"> <i class="fa fa-chrome"></i> <span>菜单1</span> <i class="fa fa-2x fa-angle-down"></i> </div> <ul class="subMenuBox"> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> <li><span class="subMenu">菜单1.1</span></li> <li><span class="subMenu">菜单1.2</span></li> <li><span class="subMenu">菜单1.3</span></li> </ul> </li> </ul> </div> <!-- 作者:15934179313@163.com 时间:2016-08-03 描述:第二个手风琴菜单 --> <div id="menuBox02" class="menuBox"> <div class="spMenuBox"> <div class="spMenuItem"> <div class="spMenu"> <i class="fa fa-chrome"></i> <span>菜单1</span> <i class="fa fa-2x fa-angle-down"></i> </div> <div class="subMenuBox"> <div><span class="subMenu">菜单1.1</span></div> <div><span class="subMenu">菜单1.2</span></div> <div><span class="subMenu">菜单1.3</span></div> </div> </div> <div class="spMenuItem"> <div class="spMenu"> <i class="fa fa-chrome"></i> <span>菜单1</span> <i class="fa fa-2x fa-angle-down"></i> </div> <div class="subMenuBox"> <div><span class="subMenu">菜单1.1</span></div> <div><span class="subMenu">菜单1.2</span></div> <div><span class="subMenu">菜单1.3</span></div> </div> </div> <div class="spMenuItem"> <div class="spMenu"> <i class="fa fa-chrome"></i> <span>菜单1</span> <i class="fa fa-2x fa-angle-down"></i> </div> <div class="subMenuBox"> <div><span class="subMenu">菜单1.1</span></div> <div><span class="subMenu">菜单1.2</span></div> <div><span class="subMenu">菜单1.3</span></div> </div> </div> </div> </div> </div> </body> <script> $().ready(function() { initLeftNavHeight(); initMenu(); }) /**初始化左侧导航栏高度**/ function initLeftNavHeight() { initHeight(); function initHeight() { var total = document.documentElement.clientHeight; var topHeight = $("#top").height(); $("#leftNav").height(total - topHeight); } document.body.onresize = function() { initHeight(); } } /**初始化菜单选项**/ function initMenu() { //配置第一个手风琴的基本参数 var config01 = { //配置菜单的MenuBoxId menuBoxId: "#menuBox01", //是否可以打开多个上级菜单 multiple: true, //初始化打开的 openIndex: [0,2] } menuBox.init(config01); //配置第二个手风琴的基本参数 var config02 = { //配置菜单的MenuBoxId menuBoxId: "#menuBox02", //是否可以打开多个上级菜单 multiple: false, //初始化打开的上级菜单的index数组 openIndex: [-1, 1] } menuBox.init(config02); } </script> </html>
menuBox.css:
body { margin: 0; } ul { list-style: none; padding: 0; margin: 0; } .left-nav { background: lightgray; height: 100%; overflow-y: overlay; position: absolute; /**flexbox兼容**/ display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ display: -moz-box; /* OLD - Firefox 19- (doesn't work very well) */ display: -ms-flexbox; /* TWEENER - IE 10 */ display: -webkit-flex; /* NEW - Chrome */ display: flex; /**flexbox兼容**/ -webkit-box-orient: horizontal; -webkit-flex-direction: row; -moz-flex-direction: row; -ms-flex-direction: row; -o-flex-direction: row; flex-direction: row; } /**菜单box**/ .menuBox { width: 300px; margin: 5px; } /**默认不显示二级菜单**/ .menuBox .subMenuBox { display: none; } /**一级菜单样式**/ .spMenuBox>*>.spMenu { align-items: center; background: darkslateblue; border-bottom: 1px solid lightgray; cursor: pointer; color: white; /**flexbox兼容**/ display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ display: -moz-box; /* OLD - Firefox 19- (doesn't work very well) */ display: -ms-flexbox; /* TWEENER - IE 10 */ display: -webkit-flex; /* NEW - Chrome */ display: flex; /**flexbox兼容**/ -webkit-box-orient: horizontal; -webkit-flex-direction: row; -moz-flex-direction: row; -ms-flex-direction: row; -o-flex-direction: row; flex-direction: row; /**flexbox兼容**/ -webkit-justify-content: space-around; -webkit-box-pack: space-around; -moz-box-pack: space-around; -ms-flex-pack: space-around; justify-content: space-around; /**user-select兼容**/ -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; -o-user-select: none; user-select: none; } /**最后一个一级菜单样式**/ .spMenuBox>*:last-child>.spMenu { align-items: center; background: darkslateblue; border-bottom: 0px; color: white; cursor: pointer; /**flexbox兼容**/ display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ display: -moz-box; /* OLD - Firefox 19- (doesn't work very well) */ display: -ms-flexbox; /* TWEENER - IE 10 */ display: -webkit-flex; /* NEW - Chrome */ display: flex; /**flexbox兼容**/ -webkit-box-orient: horizontal; -webkit-flex-direction: row; -moz-flex-direction: row; -ms-flex-direction: row; -o-flex-direction: row; flex-direction: row; /**flexbox兼容**/ webkit-justify-content: space-around; -webkit-box-pack: space-around; -moz-box-pack: space-around; -ms-flex-pack: space-around; justify-content: space-around; /**user-select兼容**/ -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; -o-user-select: none; user-select: none; } /**箭头切换用动画实现**/ .fa-angle-down { -webkit-transition: all 0.5s ease; -moz-transition: all 0.5s ease; -ms-transition: all 0.5s ease; -o-transition: all 0.5s ease; transition: all 0.5s ease; } .spMenuItem.active>.spMenu>.fa-angle-down { -webkit-transform: rotate(-180deg); -moz-transform: rotate(-180deg); -ms-transform: rotate(-180deg); -o-transform: rotate(-180deg); transform: rotate(-180deg); } /**二级菜单样式*/ .subMenuBox>*>.subMenu { align-items: center; background: #ccc; border-bottom: 1px solid lightyellow; cursor: pointer; padding: 5px 10px; /**flexbox兼容**/ display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ display: -moz-box; /* OLD - Firefox 19- (doesn't work very well) */ display: -ms-flexbox; /* TWEENER - IE 10 */ display: -webkit-flex; /* NEW - Chrome */ display: flex; /**flexbox兼容**/ -webkit-box-orient: horizontal; -webkit-flex-direction: row; -moz-flex-direction: row; -ms-flex-direction: row; -o-flex-direction: row; flex-direction: row; /**user-select兼容**/ -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; -o-user-select: none; user-select: none; } /**最后一个二级菜单样式**/ .subMenuBox>*:last-child>.subMenu { align-items: center; background: #ccc; border-bottom: 0px; cursor: pointer; padding: 5px 10px; /**flexbox兼容**/ display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ display: -moz-box; /* OLD - Firefox 19- (doesn't work very well) */ display: -ms-flexbox; /* TWEENER - IE 10 */ display: -webkit-flex; /* NEW - Chrome */ display: flex; /**flexbox兼容**/ -webkit-box-orient: horizontal; -webkit-flex-direction: row; -moz-flex-direction: row; -ms-flex-direction: row; -o-flex-direction: row; flex-direction: row; /**user-select兼容**/ -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; -o-user-select: none; user-select: none; }
menuBox.js:
/** * 配置菜单 * 示例: * 配置基本参数 * var config = { * //配置菜单的MenuBoxId * menuBoxId: "#menuBox01", * //是否可以打开多个上级菜单 * multiple: true, * //初始化打开的菜单数组 * openIndex: [1, 3, 5] * } * menuBox.init(config); * * @author DarkRanger * http: //www.cnblogs.com/wrcold520/ */ ! function($) { if($ == undefined) { throw new Error("please put your jquery.js top of menuBox.js!") } var menuBox = function() {}; //要配置的menuBox的菜单id menuBox.menuBoxId = undefined; //是否可以显示多个上级菜单的子菜单 menuBox.multiple = false; //默认关闭所有一级菜单 menuBox.openIndex = []; //menuBox初始化方法 menuBox.init = function(config) { var cntMenuBox = new menuBox(); //定义上级菜单spMenu数组 var spMenus; if(config.menuBoxId == undefined) { throw new Error("your config has not 'menuBoxId', please make sure your menuBox is existed!"); } else { cntMenuBox.menuBoxId = $(config.menuBoxId) ? config.menuBoxId : undefined; } if(config.multiple == undefined) { console.warn("your config has not 'multiple', default value is false which means you can open only one spMenu at the same time!"); } else { cntMenuBox.multiple = config.multiple; } if(config.openIndex == undefined) { console.warn("your config has not 'openIndex', default value is a Array which's length is 0!"); } else if(!config.openIndex instanceof Array) { throw new Error("your config 'openIndex' should be a number Array"); } else { cntMenuBox.openIndex = unique(config.openIndex, false); } //确定对应的menuBox cntMenuBox.menuBoxId = config.menuBoxId; //是否打开其他某一个的时候关闭其他选项 var closeOthers = !cntMenuBox.multiple; //初始化点击事件 initClickEvent(cntMenuBox, closeOthers); //确定上级菜单数组 spMenus = $(cntMenuBox.menuBoxId + " .spMenu"); //打开传入的数组 for(var i in cntMenuBox.openIndex) { var index = cntMenuBox.openIndex[i]; var spMenu = spMenus[index]; if(spMenu) { openSpMenu(cntMenuBox.menuBoxId, index); if(!cntMenuBox.multiple) { break; } } } } function unique(arr) { var result = [], hash = {}; for(var i = 0, elem; (elem = arr[i]) != null; i++) { if(!hash[elem]) { result.push(elem); hash[elem] = true; } } return result; } //初始化点击事件 function initClickEvent(menuBox, closeOthers) { $(menuBox.menuBoxId + " .spMenu").on("click", function() { var cntSpMenu$ = $(this); //要切换的元素 cntSpMenu$.next().slideToggle(); cntSpMenu$.parent().toggleClass("active") var cntSpMenu = cntSpMenu$['context']; if(closeOthers == true) { var spMenus = $(menuBox.menuBoxId + " .spMenu"); $.each(spMenus, function(index, spMenu) { if(cntSpMenu != spMenu) { closeSpMenu(menuBox.menuBoxId, index); } }); } }); } //打开某一个item function openSpMenu(menuBoxId, index) { //要切换的元素 var spItem = $(menuBoxId + " .spMenu:eq(" + index + ")"); spItem.next().slideDown(); spItem.parent().addClass("active") } //关闭某一个item function closeSpMenu(menuBoxId, index) { //要切换的元素 var spItem = $(menuBoxId + " .spMenu:eq(" + index + ")"); spItem.next().slideUp(); spItem.parent().removeClass("active") } //切换某一个item function toggleSpMenu(menuBoxId, index) { //要切换的元素 var spItem = $(menuBoxId + " .spMenu:eq(" + index + ")"); spItem.next().slideToggle(); spItem.parent().toggleClass("active") } window.menuBox = menuBox; }($);
附上源码: