目录
效果图片:
具体实现:
html:
<!-- 导航栏主体 -->
<div class="left-menu hide-menu">
<!-- 顶部标题 -->
<div>导航栏</div>
<!-- 链接 -->
<div class="menu-item-hasChild menu-item">
<p>菜单一</p>
<span class="icon">></span>
</div>
<div class="menu-first-items">
<ul>
<li>
<div class="li-text li-underline">选项一</div>
</li>
<li>
<div class="li-text li-underline">选项二</div>
</li>
<li>
<div class="li-text li-underline">选项三</div>
</li>
<li>
<div class="li-text">选项四</div>
</li>
</ul>
</div>
<div class="menu-no-child menu-item">菜单二</div>
<div class="menu-no-child menu-item">菜单三</div>
<div class="menu-item-hasChild menu-item">
<p>菜单四</p>
<span class="icon">></span>
</div>
<div class="menu-first-items">
<ul>
<li>
<div class="li-text li-underline">选项一</div>
</li>
<li>
<div class="li-text li-underline">选项二</div>
</li>
<li>
<div class="li-text li-underline">选项三</div>
</li>
<li>
<div class="li-text">选项四</div>
</li>
</ul>
</div>
<div class="menu-item-hasChild menu-item">
<p>菜单五</p>
<span class="icon">></span>
</div>
<div class="menu-first-items">
<ul>
<li>
<div class="li-text li-underline">选项一</div>
</li>
<li>
<div class="li-text li-underline">选项二</div>
</li>
<li>
<div class="li-text li-underline">选项三</div>
</li>
<li>
<div class="li-text">选项四</div>
</li>
</ul>
</div>
<div class="menu-no-child menu-item">菜单六</div>
</div>
<!-- 展开与关闭导航区的模拟按键 -->
<div class="open-close reverse-condition"> < </div>
css:
一级导航标题右侧的小箭头以及控制展开、隐藏导航栏的右侧“按钮”的图标都是用符号“<”来做的,就是html中的> 数学中的交集和并集符号也可以做。利用transform中的变换函数可以将两个边的方向往外拉伸,就不会显得又扁又尖。
右侧控制导航栏展开和隐藏的模拟按钮,利用3D变换+透视距离来实现一个矩形的效果。
:root {
font-family: "Courier New", Courier, monospace;
}
* {
box-sizing: border-box;
overflow: hidden;
color: black;
}
.left-menu {
position: fixed;
top: 0;
left: 0;
width: 175px;
height: 100vh;
background-color: rgb(246, 246, 246);
border-right: 2px solid white;
text-align: center;
font-size: 1.2rem;
transition: left 0.2s linear 0.1s;
}
.hide-menu {
left: -180px;
}
/** 导航栏 */
.left-menu > div:nth-child(1) {
margin-top: 2rem;
margin-bottom: 1.5rem;
border: 0px;
font-size: 1.4rem;
font-weight: 900;
}
/** 全部一级菜单 */
.menu-item {
padding: 1rem;
width: 100%;
font-weight: 800;
border-radius: 0.3rem;
border-top: 0.1px solid rgb(201, 195, 195);
border-bottom: 0.1px solid rgb(201, 195, 195);
}
.menu-item:hover {
cursor: pointer;
background-color: rgb(224, 224, 224);
}
/** 可打开的菜单 */
.menu-item-hasChild {
position: relative;
align-items: center;
}
.menu-item-hasChild > p {
margin: 0;
}
.icon {
position: absolute;
right: 25px;
top: 50%;
font-size: 1rem;
font-weight: 100;
transition: transform 0.3s linear;
transform: translate(0, -50%) rotate(90deg) scaleY(1.8);
opacity: 0.5;
z-index: 2;
}
/** 可打开的菜单被点击后icon的样式 */
.reverse-icon {
transform: translate(0, -50%) rotate(270deg) scaleY(1.8);
}
/** 可打开的菜单的直属列表 */
.menu-first-items {
height: 0px;
margin: 0px;
padding: 0px;
overflow: hidden;
transition: height 0.3s ease-out 0.1s;
}
ul {
margin: 0px;
padding: 0px;
}
.ul-active {
height: 140px;
}
li {
list-style: none;
}
.li-text {
font-size: 1.1rem;
line-height: 35px;
height: 35px;
width: 70%;
margin: 0 auto;
}
.li-underline {
border-bottom: 0.5px solid rgba(104, 104, 104, 0.2);
}
.li-text:hover {
background-color: rgb(224, 224, 224);
cursor: pointer;
border-radius: 0.5rem;
}
/** 展开与关闭导航航 */
.open-close {
position: fixed;
padding: 20px;
font-size: 2rem;
font-weight: bolder;
top: 50%;
left: 156px;
background-color: rgb(246, 246, 246);
transition: left 0.2s linear 0.1s, transfrom 0.2s linear 0.1s;
transform: translate(0, -50%) perspective(100px) rotateY(70deg) scaleY(1.6);
}
.open-close:hover {
cursor: pointer;
background-color: rgb(200, 200, 200);
}
.reverse-condition {
margin: 0;
left: -20px;
transform: translate(0, -50%) perspective(100px) rotateY(70deg) scaleY(1.6)
rotateZ(180deg);
}
.bg-color{
background-color: #fecc90;
}
JavaScript:
1、当某个一级菜单被点击时,控制展开二级菜单和一级菜单右侧的小图标翻转变化
2、当有一个一级菜单被打开,在其没有被关闭的情况下,又点击另一个一级菜单,则将前一个一级菜单关闭
let menuItems = document.getElementsByClassName("menu-item-hasChild");
let items = document.getElementsByClassName("menu-first-items");
let noChildItem = document.getElementsByClassName('menu-no-child');
let icons = document.getElementsByClassName("icon");
/** 记录当前打开的一级菜单是哪个 没有打开任何菜单的状态 默认为-1 */
let currentDisplayIndex = -1;
for (let i = 0; i < menuItems.length; i++) {
menuItems[i].onclick = function () {
/** 再次点击已打开的菜单,关闭此菜单 */
if (currentDisplayIndex === i) {
items[currentDisplayIndex].classList.toggle("ul-active");
icons[currentDisplayIndex].classList.toggle("reverse-icon");
menuItems[currentDisplayIndex].classList.toggle('bg-color');
currentDisplayIndex = -1
return;
}
/** 关闭前一个被打开的菜单 打开当前要打开的菜单 */
if (currentDisplayIndex != -1) {
items[currentDisplayIndex].classList.toggle("ul-active");
icons[currentDisplayIndex].classList.toggle("reverse-icon");
menuItems[currentDisplayIndex].classList.toggle('bg-color');
items[i].classList.toggle("ul-active");
icons[i].classList.toggle("reverse-icon");
menuItems[i].classList.toggle('bg-color');
}
/** 没有任何菜单被打开时 打开新菜单 */
else{
items[i].classList.toggle("ul-active");
icons[i].classList.toggle("reverse-icon");
menuItems[i].classList.toggle('bg-color');
}
// 清除没有下一级列表的菜单的背景
if(currentDisplayIndex === -1){
for(let e of noChildItem){
if(e.classList.contains('bg-color')){
e.classList.toggle('bg-color');
}
}
}
currentDisplayIndex = i;
};
}
// 当没有子菜单的菜单被点击
for(let e of noChildItem){
e.addEventListener('click',()=>{
// 处理非同类菜单
for(let i = 0 ; i < items.length ; i ++){
if(items[i].classList.contains('ul-active')){
items[i].classList.toggle('ul-active');
icons[i].classList.toggle('reverse-icon');
menuItems[i].classList.toggle('bg-color');
}
}
// 去除其他同类子菜单的背景色
for(let i = 0 ; i < noChildItem.length ; i ++){
if(noChildItem[i].classList.contains('bg-color')){
noChildItem[i].classList.toggle('bg-color');
}
}
// 为自己添加背景色
e.classList.toggle('bg-color');
currentDisplayIndex = -1;
})
}
// 导航栏的显现与隐藏
let OC = document.getElementsByClassName("open-close")[0];
let menu = document.getElementsByClassName("left-menu")[0];
OC.onclick = function () {
OC.classList.toggle("reverse-condition");
menu.classList.toggle("hide-menu");
};