JavaScript实战之带收放动画效果的导航菜单


Posted in Javascript onAugust 16, 2016

虽然有很多插件可用,但为了共同提高,我做了一系列JavaScript实战系列的实例,分享给大家,前辈们若有好的建议,请务必指出,免得误人子弟啊!
今天是第一战:带收放动画效果的菜单,效果如下图:(样式有点丑(-^-)) 
( 由于在写本文时,用的编辑器不同,暂时添加不了演示效果,这里有:最终完整代码和演示 ) 

JavaScript实战之带收放动画效果的导航菜单

动画效果:鼠标hover改变所有目标的背景和字体颜色,鼠标移动到‘首页导航',显示下面的分组菜单,分组菜单有子菜单,点击可缩放,带动画过度效果!而且,可以随便添加和删除导航菜单和子菜单,不影响效果! 

如何实现呢? 

第一步:用什么来实现菜单?HTML代码设计如下,遵循JS代码和HTML代码分离的原则!这里你看不到一句JS代码 

JavaScript实战之带收放动画效果的导航菜单

未应用样式之前是这个样子的:很古老吧!!! 

JavaScript实战之带收放动画效果的导航菜单

第二步:CSS样式。鼠标hover改变所有目标的背景和字体颜色,直接用CSS的transition和:hover,而其他的CSS样式布局就不全部列举了,大家自己动手吧,主要注意以下几点: 

#ul{
 ....
 z-index: 100;
 }
 #ul li{
 display: inline-block;
 position: relative;
 top: 0;
 left: -25px;
 width: 10%;
 min-width: 70px;
 height: 30px;
 text-align: center;
 line-height: 30px;
 border: 1px solid gray;
 border-radius:10px;
 background-color: aliceblue;
 cursor: pointer;
 -webkit-transition: all ease-in-out 0.3s;
 -moz-transition: all ease-in-out 0.3s;
 -ms-transition: all ease-in-out 0.3s;
 -o-transition: all ease-in-out 0.3s;
 transition: all ease-in-out 0.3s;
 }
 #ul li:hover{background-color: aquamarine;color: red;}
 ...
 .show-hide:hover{background-color: beige}
 .a-div{
 background-color: aquamarine;
 border-radius:10px;
 color: black;
 display: none;
 opacity: 0
 }
 .a{
 z-index: -1;
 display: block;
 ...
 }

第三步:这一步是重点。如果给每个菜单选项和分组都添加事件监听,个人觉得好麻烦,且代码量肯定多不少,有没有什么办法就在一个元素上加监听就能实现呢?

答案肯定是有的,利用事件的冒泡机制!在父元素ul标签上添加事件监听,而在监听函数里直接改变触发事件的元素样式就可以了,就这么简单!

代码如下:

var ul = document.getElementById('ul');
ul.addEventListener('mouseover',listener1,false);
ul.addEventListener('mouseout',listener2,false);
ul.addEventListener('click',listener3,false);
 

 因为IE8及以下版本没有addEventListener,如果要兼容,还得加attachEvent对应的代码。

第四:主角登场!实现listener1、listener2、listener3监听函数。

首先来最简单的listener1函数,代码如下:

function listener1(event){
 //event = event||window.event; //兼容IE8及以前版本
 var target = event.target||event.srcElement; //兼容IE8及以前版本
 if(target.tagName.toLowerCase() === 'li'){
 var div1 = target.getElementsByTagName('div')[0];
 div1.style.display = 'block';
 var i = 0;
 var id;
 (function foo(){
 if(i>=1){clearTimeout(id);id=null;return;}
 i+=0.2;
 div1.style.opacity = i;
 id = setTimeout(function(){clearTimeout(id);foo()},30);  


})();  

 }

 }

同样,一切为了IE8及更旧版本。

1.因为它的event没有target属性,只有相对应得srcElement属性

2.而这一句event = event||window.event;这里其实是可以省略的,只有当用属性来设置注册事件监听时,如ul.onmouseover = function(){},或<ul onmouseover='func'>,IE8及更旧版本只能通过window.event来取得当前的Event对象

好了,现在获得了当前触发事件的target,事情就简单很多了,通过他就可以改变它自己和它的亲戚!

下面是listener2函数,用在mouseout时触发,主要是操控target的子元素DIV,代码如下:

function listener2(event){
 //event = event||window.event;
 var target = event.target||event.srcElement;
 if(target.tagName.toLowerCase() === 'li'){
 var div1 = target.getElementsByTagName('div')[0];
 div1.onmouseover = function(){
 div1.style.display = 'block';
 div1.style.opacity = 1;
 };
 div1.onmouseout = function(){
 div1.style.display = 'none';
 div1.style.opacity = 0;
 };
 div1.style.display = 'none'; //这一组是为了实现当鼠标从上方出去时隐藏div1
 div1.style.opacity = 0;
 }
 }

好了,到这里,已经实现了大部分效果了,还有最后一步,那就是1号主角了:listener3函数,它主要负责鼠标点击时的缩放效果!

实现原理:  

1.函数外面定义一个bool变量当做开关,鼠标点一下开,再点一下关;

2.通过setTimeout来实现动画效果,动态的改变子菜单的height和opacity属性,还有display属性;

完整代码如下:

var bool = true;
 function listener3(event) {
 var event = event || window.event;
 var target = event.target || event.srcElement;
 if (target.className === 'show-hide') {
 var parent = target.parentElement;
 var adiv = parent.getElementsByClassName('a-div')[0];
 if (window.getComputedStyle(adiv,null).opacity>0.5){bool=false}else{bool=true}
 var height = 90,
 changeH,
 opacity,
 id;
 if (bool) {
 changeH = 0;
 opacity = 0;
 target.innerHTML = '财经 -';
 (function show() {
 if (changeH > height) {clearTimeout(id);return}
 changeH += 5;
 opacity += 0.06;
 //console.log('opacity:'+adiv.style.opacity+',height :'+adiv.style.height);
 adiv.style.height = changeH + 'px';
 adiv.style.opacity = opacity;
 adiv.style.display = 'block';
 id = setTimeout(function () {









 clearTimeout(id);
 show();
 }, 16.7);
 })();

 bool = false;
 } else {
 changeH = height;
 opacity = 1;
 target.innerHTML = '财经 +';
 (function hidden() {
 if (changeH < 0) {clearTimeout(id);adiv.style.display = 'none';return}
 changeH -= 10;
 opacity -= 0.11;
 //console.log('opacity:'+adiv.style.opacity+',height :'+adiv.style.height);
 adiv.style.height = changeH + 'px';
 adiv.style.opacity = opacity;
 id = setTimeout(function () {










 clearTimeout(id);
 hidden();
 }, 16.7);
 })();
 bool = true;
 }
 }
 }

注意几点:  

1.记得清除setTimeout的ID,然后退出,否则死循环,如if (changeH < 0) {clearTimeout(id);adiv.style.display = 'none';return}

2.setTimeout的延迟时间设置为16.7是因为符合屏幕的刷新率60FPS,看着舒服

3.调试过程中,设置changeH和opacity的递增递减值时,记得打印出来,方便调试:

console.log('opacity:'+adiv.style.opacity+',height :'+adiv.style.height);  

4.最后,整个菜单的实现中,最关键的是下面这一句,如果没有这一句,你无法完美实现所有功能,比如:你点开一组子菜单,然后移动到其它组点击的时候,情况将有很大不同;而window.getComputedStyle用这个的原因是,首次打开时,点任意组的第一下都没反应,因为直接通过event.target在点第一下时是取不到opacity值的。

if (window.getComputedStyle(adiv,null).opacity>0.5){bool=false}else{bool=true};

不过,IE9以下不支持getComputedStyle方法,IE的Element对象有currentStyle属性;

如果你对CSS的处理不是很熟悉,看看我的总结:用原生JS读写CSS样式的方法总结

如果你想多了解setTimeout()方法的应用,看看这个:你真的知道setTimeout是如何运行的吗

对于事件的处理机制,可以看看这个:DOM中的事件处理概览与原理的全面剖析

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript 继承实现例子
Aug 12 Javascript
Javascript数组的排序 sort()方法和reverse()方法
Jun 04 Javascript
Jquery增加鼠标中间功能mousewheel的实例代码
Sep 05 Javascript
jquery的总体架构分析及实现示例详解
Nov 08 Javascript
JavaScript数据结构和算法之图和图算法
Feb 11 Javascript
Js可拖拽放大的层拖动特效实现方法
Feb 25 Javascript
js+html5实现可在手机上玩的拼图游戏
Jul 17 Javascript
javascript运动效果实例总结(放大缩小、滑动淡入、滚动)
Jan 08 Javascript
JS中parseInt()和map()用法分析
Dec 16 Javascript
JS中传递参数的几种不同方法比较
Jan 20 Javascript
select标签设置默认选中的选项方法
Mar 02 Javascript
webpack4简单入门实例
Sep 06 Javascript
js 自带的sort() 方法全面了解
Aug 16 #Javascript
JavaScript实战之菜单特效
Aug 16 #Javascript
深入理解js generator数据类型
Aug 16 #Javascript
js 创建对象 经典模式全面了解
Aug 16 #Javascript
js 上传文件预览的简单实例
Aug 16 #Javascript
js removeChild 方法深入理解
Aug 16 #Javascript
关于javascript中限定时间内防止按钮重复点击的思路详解
Aug 16 #Javascript
You might like
PHP 最大运行时间 max_execution_time修改方法
2010/03/08 PHP
重新认识php array_merge函数
2014/08/31 PHP
解决Laravel无法使用COOKIE和SESSION的问题
2019/10/16 PHP
PHP 范围解析操作符(::)用法分析【访问静态成员和类常量】
2020/04/14 PHP
Thinkphp 框架扩展之类库扩展操作详解
2020/04/23 PHP
Javascript实现div层渐隐效果的方法
2015/05/30 Javascript
jQuery-1.9.1源码分析系列(十)事件系统之事件体系结构
2015/11/19 Javascript
在JavaScript中使用JSON数据
2016/02/15 Javascript
Javascript设计模式之装饰者模式详解篇
2017/01/17 Javascript
JavaScript获取ul中li个数的方法
2017/02/13 Javascript
axios发送post请求,提交图片类型表单数据方法
2018/03/16 Javascript
详解Vue webapp项目通过HBulider打包原生APP
2018/06/29 Javascript
js回溯法计算最佳旅行线路代码实例
2019/09/11 Javascript
微信小程序本地存储实现每日签到、连续签到功能
2019/10/09 Javascript
原生js实现照片墙效果
2020/10/13 Javascript
[15:20]DOTA2亚洲邀请赛总决赛开幕式表演:羽泉献唱
2017/04/05 DOTA
使用Python编写Linux系统守护进程实例
2015/02/03 Python
Python编程中对super函数的正确理解和用法解析
2016/07/02 Python
python web基础之加载静态文件实例
2018/03/20 Python
Python 经典面试题 21 道【不可错过】
2018/09/21 Python
pycharm debug功能实现跳到循环末尾的方法
2018/11/29 Python
python flask 如何修改默认端口号的方法步骤
2019/07/12 Python
Python-copy()与deepcopy()区别详解
2019/07/12 Python
Django 开发环境与生产环境的区分详解
2019/07/26 Python
python实现图像全景拼接
2020/03/27 Python
Python 连接 MySQL 的几种方法
2020/09/09 Python
美国知名的时尚购物网站:Anthropologie
2016/12/22 全球购物
Reebonz中国官网:新加坡奢侈品购物网站
2017/03/17 全球购物
运动会入场式解说词
2014/02/18 职场文书
静心口服夜广告词
2014/03/20 职场文书
项目经理任命书
2014/06/04 职场文书
交通事故一次性赔偿协议书范本
2014/11/02 职场文书
机关单位保密工作责任书
2015/05/11 职场文书
田径运动会通讯稿
2015/07/18 职场文书
2016年学校党支部公开承诺书
2016/03/25 职场文书
Python 把两层列表展开平铺成一层(5种实现方式)
2021/04/07 Python