这篇文章主要为大家详细介绍了 JavaScript 实战之带收放动画效果的导航菜单,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
虽然有很多插件可用,但为了共同提高,我做了一系列 JavaScript 实战系列的实例,分享给大家,前辈们若有好的建议,请务必指出,免得误人子弟啊!
今天是第一战:带收放动画效果的菜单,效果如下图:(样式有点丑 (-^-))
( 由于在写本文时,用的编辑器不同,暂时添加不了演示效果,这里有:{aa3aa} )
动画效果:鼠标 hover 改变所有目标的背景和字体颜色,鼠标移动到'首页导航',显示下面的分组菜单,分组菜单有子菜单,点击可缩放,带动画过度效果!而且,可以随便添加和删除导航菜单和子菜单,不影响效果!
如何实现呢?
第一步:用什么来实现菜单?html 代码设计如下,遵循 JS 代码和 HTML 代码分离的原则!这里你看不到一句 JS 代码
未应用样式之前是这个样子的:很古老吧!!!
第二步: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 的处理不是很熟悉,看看我的总结:{aa2aa}
如果你想多了解 setTimeout() 方法的应用,看看这个:{aa1aa}
对于事件的处理机制,可以看看这个:{aa0aa}
来源: http://www.phperz.com/article/17/0328/263571.html