模仿淘宝的侧边栏效果 最终实现的效果图如下所示
该侧边栏对应的html代码如下 需要说明的是该实例中的图标都是通过引用bootstrape中的图标实现的。另外,菜单项中的li的id和菜单项所对应的div的id是根据一定规律命名的,都是li的id后加“-content"命名的 ,方便以后的js操作
-
我
-
资产
-
品牌
-
直播
-
看过
-
日历
对该侧边栏进行css样式编写
#sideBar{
width:35px;
background-color: #ccc;
padding-top:100px;
position:fixed;/*生成绝对定位的元素,相对于浏览器窗口进行定位*/
min-height: 100%;
z-index:99;
}
ul{
list-style-type: none;
padding:0px;
margin-top:100px;
}
#sideBar .item{
font-size:12px;
font-family: 'Microsoft YaHei';
text-align:center;
margin-top:10px;
}
#closeBar{
position:absolute;
bottom:30px;
width:35px;
text-align: center;
cursor:pointer;
}
.nav-content{
width:200px;
position:fixed;/*会让元素脱离普通流,不占据空间*/
min-height:100%;
border:1px solid #ccc;
background-color: #e1e1e1;
opacity:0;
z-index:98;
}
.nav-con-close{
position: absolute;/*相对于最近的“positioned”祖先元素一个“positioned”元素是指position 值不是 static 的元素*/
top:5px;
right:5px;
cursor: pointer;
}
写好html、css后,编写js代码 实现侧边栏的动画效果
首先,为了防止变量被污染 创建私有作用域,在私有作用域中创建一个侧边栏的对象,并通过构造函数方法传入侧边栏id和侧边栏的关闭id,通过原型方法定义侧边栏对象的打开和关闭方法,在打开和关闭方法中添加了定义打开和关闭动画的类
//定义侧边栏的构造函数(传递的参数为侧边栏中的菜单导航元素的id和菜单导航元素中的关闭元素的id
var Sidebar=function(eId,closeBarId){
this.state='opened';//侧边栏的状态(opend或closed)
//防止闭包this的指向问题
var self=this;
this.menuBar=new Menubar();//menuBar为点击菜单栏后出现的展示信息的区域 将Menubar作为Sidebar的一个属性
//采用构造函数方法为属性赋值
this.el=document.getElementById(eId||'sideBar');
this.closeBarEl=document.getElementById(closeBarId||'closeBar');
//为菜单导航增加click监听事件 在菜单栏中阻止冒泡 使得该事件对侧边栏的关闭按钮有效
this.el.addEventListener('click',function(event){
//target只包含事件的实际目标(菜单导航元素或关闭元素)
if(event.target!==self.el){
//调用该函数 判断侧边栏的状态
self.triggerSwitch();
}
})
}
//原型对象函数
Sidebar.prototype.close=function(){
console.log('close');
//为侧边栏添加类 定义侧边栏关闭的动画效果
this.el.className='sidebar-move-left';
//为关闭按钮添加类 定义侧边栏关闭时 关闭按钮的动画效果
this.closeBarEl.className='closeBar-move-right';
//改变侧边栏的状态
this.state='closed';
};
Sidebar.prototype.open=function(){
console.log('open');
this.el.style.left='-120px';
this.el.className='sidebar-move-right';
this.closeBarEl.style.left='160px';
this.closeBarEl.className='closeBar-move-left';
this.state='opened';
};
Sidebar.prototype.triggerSwitch=function(){
console.log("进入triggerSwitch函数");
//根据状态选择是调用打开还是关闭函数
if(this.state==='opened'){
//如果当前状态是打开的 则关闭该侧边栏 并调用close()函数
console.log('调用打开函数');
this.close();
}else if(this.state==='closed'){
//如果当前状态是关闭的 则打开该侧边栏 并调用open()函数
console.log('调用关闭函数');
this.open();
}
}
var sidebar=new Sidebar();
.sidebar-move-left{
/*left:-120px;*/
-webkit-animation-name: smf;
-o-animation-name: smf;
animation-name: smf;
-webkit-animation-duration: 1s;/*动画执行时间*/
-o-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-iteration-count: 1;/*动画执行次数*/
-o-animation-iteration-count: 1;
animation-iteration-count: 1;
-webkit-animation-fill-mode: forwards;
-o-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
@keyframes smf{
from{
}to{
transform:translateX(-120px);
}
}
@-webkit-keyframes smf{
from{
}to{
transform:translateX(-120px);
}
}
.closeBar-move-right{
/*left:160px;*/
-webkit-animation-name: cmr;
-o-animation-name: cmr;
animation-name: cmr;
-webkit-animation-duration: 1s;/*动画执行时间*/
-o-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-iteration-count: 1;/*动画执行次数*/
-o-animation-iteration-count: 1;
animation-iteration-count: 1;
-webkit-animation-fill-mode: forwards;
-o-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
@keyframes cmr{
from{
}to{
/* transform:translateX(160px);
transform:rotate(405deg);
transform:scale(1.5); */
-webkit-transform:translateX(160px) rotate(405deg) scale(1.5);
transform:translateX(160px) rotate(405deg) scale(1.5);
}
}
@-webkit-keyframes cmr{
from{
}to{
/* transform:translateX(160px);
transform:rotate(405deg);
transform:scale(1.5); */
-webkit-transform:translateX(160px) rotate(405deg) scale(1.5);
transform:translateX(160px) rotate(405deg) scale(1.5);
}
}
菜单栏所对应的div实现方法如下(定义menuBar对象 )
function Menubar(){
this.currentOpenedMenuContentEl=null;//定义当前打开的菜单项
//document.querySelector()返回当前文档中的第一个匹配特定选择器的元素
this.el=document.querySelector('#sideBar ul');
this.state='allClosed';//初始化菜单项的状态全为关闭
//阻止事件冒泡,这样点击菜单项时,只响应菜单项事件 不干扰sidebar
this.el.addEventListener('click',function(e){
e.stopPropagation();
})
var self=this;
//选取出菜单栏中的li元素
this.meauList=document.querySelectorAll('#sideBar ul>li');
console.log(this.meauList);//输出正常
for (var i = 0; i < this.meauList.length; i++) {
//为li元素添加点击事件
this.meauList[i].addEventListener('click',function(e){
//获取菜单栏中点击各菜单出现的展示信息的元素的id
var menuContentEl=document.getElementById(e.currentTarget.id+'-content');
if(self.state==='allClosed'){
//添加打开时的动画(为css3中的动画重置元素的位置)
menuContentEl.style.top='0';
menuContentEl.style.left='-85px';
menuContentEl.classList.add('menuContent-move-right');
self.state='hasOpend';
self.currentOpenedMenuContentEl=menuContentEl;
}else{
console.log('关闭'+self.currentOpenedMenuContentEl.id);
self.currentOpenedMenuContentEl.className='nav-content';
// 初始化展示信息元素的位置
self.currentOpenedMenuContentEl.style.top='0';
self.currentOpenedMenuContentEl.style.left='35px';
self.currentOpenedMenuContentEl.classList.add('menuContent-move-left');
console.log('打开'+menuContentEl.id);
menuContentEl.className='nav-content';
menuContentEl.style.top='250px';
menuContentEl.style.left='35px';
menuContentEl.classList.add('menuContent-move-up');
self.state='hasOpend';
self.currentOpenedMenuContentEl=menuContentEl;
}
})
};
this.menuContentList=document.querySelectorAll(".nav-content>div.nav-con-close");
for (var i = 0; i < self.menuContentList.length; i++) {
self.menuContentList[i].addEventListener('click',function(e){
//在事件处理程序内部 对象this始终等于currentTarget的值
var menuContent=e.currentTarget.parentNode;
//menuContent.className='nav-content';
menuContent.style.top='0';
menuContent.style.left='35px';
menuContent.classList.add('menuContent-move-left');
self.state='allClosed';
})
};