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 IE 与 FF中兼容问题小结
Feb 18 Javascript
javascript 面向对象全新理练之原型继承
Dec 03 Javascript
页面回到顶部的三种实现(锚标记,js)
Oct 01 Javascript
比较常见的javascript中定义函数的区别
Nov 09 Javascript
Angular中$cacheFactory的作用和用法实例详解
Aug 19 Javascript
Web前端框架bootstrap实战【第一次接触使用】
Dec 28 Javascript
mescroll.js上拉加载下拉刷新组件使用详解
Nov 13 Javascript
纯js实现隔行变色效果
Nov 29 Javascript
layui弹出层按钮提交iframe表单的方法
Aug 20 Javascript
小程序实现左滑删除功能
Oct 30 Javascript
Layui带搜索的下拉框的使用以及动态数据绑定方法
Sep 28 Javascript
解决nuxt页面中mounted、created、watch执行两遍的问题
Nov 05 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
全国FM电台频率大全 - 13 福建省
2020/03/11 无线电
php实现的一个简单json rpc框架实例
2015/03/30 PHP
php pdo oracle中文乱码的快速解决方法
2016/05/16 PHP
Thinkphp批量更新数据的方法汇总
2016/06/29 PHP
PHP检查网站是否宕机的方法示例
2017/07/24 PHP
phpStudy配置多站点多域名和多端口的方法
2017/09/01 PHP
jquery 日期分离成年月日的代码
2010/05/14 Javascript
Javascript绝句欣赏 一些经典的js代码
2012/02/22 Javascript
Js,alert出现乱码问题的解决方法
2013/06/19 Javascript
node.js中的fs.fchownSync方法使用说明
2014/12/16 Javascript
Jquery中$.post和$.ajax的用法小结
2015/04/28 Javascript
Nodejs实现批量下载妹纸图
2015/05/28 NodeJs
Javascript之Date对象详解
2016/06/07 Javascript
js计算系统当前日期是星期几的方法
2016/07/14 Javascript
JavaScript与java语言有什么不同
2016/09/22 Javascript
Node.js获取前端ajax提交的request信息
2017/02/20 Javascript
微信小程序手势操作之单触摸点与多触摸点
2017/03/10 Javascript
JS实现数组去重及数组内对象去重功能示例
2019/02/02 Javascript
Vue表单控件数据绑定方法详解
2020/02/05 Javascript
vue 路由meta 设置导航隐藏与显示功能的示例代码
2020/09/04 Javascript
python中requests爬去网页内容出现乱码问题解决方法介绍
2017/10/25 Python
python pandas cumsum求累计次数的用法
2019/07/29 Python
PySide2出现“ImportError: DLL load failed: 找不到指定的模块”的问题及解决方法
2020/06/10 Python
Python StringIO及BytesIO包使用方法解析
2020/06/15 Python
Ubuntu20下的Django安装的方法步骤
2021/01/24 Python
html5中valid、invalid、required的定义
2014/02/21 HTML / CSS
6PM官网:折扣鞋、服装及配饰
2018/08/03 全球购物
Hoover胡佛官网:美国吸尘器和洗地机品牌
2019/01/09 全球购物
刘胡兰的英雄事迹材料
2014/02/11 职场文书
化妆师职业生涯规划书
2014/02/16 职场文书
经销商年会策划方案
2014/05/29 职场文书
党支部创先争优承诺书
2014/08/30 职场文书
学校师德师风自我剖析材料
2014/09/29 职场文书
中学生综合素质自我评价
2015/03/06 职场文书
详解python字符串驻留技术
2021/05/21 Python
一篇文章告诉你如何实现Vue前端分页和后端分页
2022/02/18 Vue.js