最近在学习web,想用一些实践来练习下,就想拿自己的blog下手~,这里备份下如何淡入淡出导航菜单。
CONTENTS
备注:
1) 由于作者初学web开发,没有开发经验,一路跌跌撞撞,各种弯路,最后是google加运气才实现的效果,实现方式和效率可能都不大好,还请路过的高手多多指导~
2) 实现该效果用到了一部分别人的【 源码 】,这里表示感谢,版权归原作者所有。
3) 作者使用的wordpress模板也是别人共享的,这里表示感谢,版权归原作者所有。
由于参考的代码的wp版本比较老了,不好直接在作者本地的blog中进行复制粘贴,因此需要一步一步来:
实现原理分析:
讲【 源码 】提供的demo下载下来进行分析,原作者在blog中指出,有3个文件比较重要, header.php , style.css 和 js/menu.js .
我们这里先看下menu.js:
。。。。 。。。。 var MenuList = Class.create(); MenuList.prototype = { 。。。。 。。。。 initialize: function(id, opacity) { // 获取菜单列表 this.obj = document.getElementById(id); if (!this.obj) { return; } // 对菜单列表内的所有菜单进行处理 var menus = this.obj.childNodes; for (var i = 0; i < menus.length; i++) { var menu = menus[i]; if (menu.tagName == 'LI') { // 构建菜单 new Menu(menu, opacity); } } } } 。。。。 。。。。 var Menu = Class.create(); Menu.prototype = { 。。。。 。。。。 initialize: function(target, opacity) { this.util = new MenuUtil(); // 获取目标菜单 (没多余元素) this.obj = this.util.cleanWhitespace(target); /* shade 2008/09/01 CHANGE START */ // 定义透明度, 默认透明 this.opacity = 0; this.maxopacity = opacity || 1; /* shade 2008/09/01 CHANGE END */ // 获取菜单 this.menu = this.obj.childNodes // 重要! 如果菜单不包含菜单项, 则不进行处理 if (this.menu.length < 2) { return; } // 菜单标题和菜单体 this.title = this.menu[0]; this.body = this.menu[1]; // 定义初始样式 this.util.setStyle(this.body, 'visibility', 'hidden'); this.util.setStyle(this.body, 'position', 'absolute'); this.util.setStyle(this.body, 'overflow', 'hidden'); this.util.setStyle(this.body, 'display', 'block'); // 添加监听器 this.addListener(this.obj, 'mouseover', this.util.bind(this, this.activate), false); this.addListener(this.obj, 'mouseout', this.util.bind(this, this.deactivate), false); }, /** * 激活方法 * 当鼠标移动到菜单标题是激活 */ activate: function() { // 获取当前菜单体的位置 var pos = this.util.cumulativeOffset(this.title); var left = pos[0]; var top = pos[1] + this.util.getHeight(this.title); // 定义激活时样式 this.util.setStyle(this.body, 'left', left + 'px'); this.util.setStyle(this.body, 'top', top + 'px'); this.util.setStyle(this.body, 'visibility', 'visible'); this.util.setStyle(this.body, 'opacity', this.opacity); this.util.setStyle(this.body, 'filter', 'alpha(opacity=' + this.opacity * 100 + ')'); /* shade 2008/09/01 ADD START */ if(this.tid) { clearTimeout(this.tid); } // 不断加强菜单的不透明度 this.tid = setInterval(this.util.bind(this, this.appear), 30); /* shade 2008/09/01 ADD END */ }, /** * 解除方法 * 当鼠标移动出菜单标题是激活 */ deactivate: function(){ /* shade 2008/09/01 ADD START */ if(this.tid) { clearTimeout(this.tid); } // 不断减弱菜单的不透明度 this.tid = setInterval(this.util.bind(this, this.fade), 30); /* shade 2008/09/01 ADD END */ /* shade 2008/09/01 DELETE START */ // 定义解除时样式 //this.util.setStyle(this.body, 'visibility', 'hidden'); /* shade 2008/09/01 DELETE END */ }, /* shade 2008/09/01 ADD START */ /** * 加强不透明度, 直到最大不透明度 */ appear: function() { this.opacity += 0.1; if(this.opacity >= this.maxopacity) { this.opacity = this.maxopacity; // 取消循环调用 clearTimeout(this.tid); } // 重新设定透明度 this.util.setStyle(this.body, 'opacity', this.opacity); this.util.setStyle(this.body, 'filter', 'alpha(opacity=' + this.opacity * 100 + ')'); }, /** * 减小不透明度, 直到完全透明隐藏菜单 */ fade:function() { this.opacity -= 0.1; if(this.opacity <= 0) { this.opacity = 0; // 隐藏菜单 this.util.setStyle(this.body, 'visibility', 'hidden'); // 取消循环调用 clearTimeout(this.tid); } // 重新设定透明度 this.util.setStyle(this.body, 'opacity', this.opacity); this.util.setStyle(this.body, 'filter', 'alpha(opacity=' + this.opacity * 100 + ')'); }, /* shade 2008/09/01 ADD END */ /** * 监听方法 * element: 监听对象 * name: 监听方法 * observer: 执行的方法 * useCapture: 浏览器调用事件的方式 (true 为 Capture 方式, false 为 Bubbling 方式) */ addListener: function(element, name, observer, useCapture) { if(element.addEventListener) { element.addEventListener(name, observer, useCapture); } else if(element.attachEvent) { element.attachEvent('on' + name, observer); } } } 。。。。 。。。。 /** 添加到页面加载事件 */ window.onload = function(e) { new MenuList('menus', 0.9); }
代码虽然比较多,但是很清晰,大牛写的就是不一样~。
主要逻辑为:
在window.onload回调函数中将id为”menus”的节点传入MenuList,然后MenuList对其中的各个子menu添加监听器,监听鼠标移入移出,并在监听代码中使用定时器,来递增,递减menu的透明度,从而实现淡入淡出效果。
然后再看下header.php:
<!-- 加载菜单效果的 JavaScriot --> <script type="text/javascript" src="<?php bloginfo('template_url'); ?>/js/menu.js"></script> 。。。。 。。。。 <!-- 分类菜单 START --> <div id="menubar"> <ul id="menus" class="menus"> 。。。。 。。。。 </ul> </div>
header.php中加入了上面的js脚本,并且在生成菜单时制定了根ul的id为”menus”,这样,当网页被载入后,window.onload方法被回调,监听器就起作用了。
style.css文件中主要是提供了menu的各种样式,这里就不分析了。
自己的blog修改过程:
实现原理分析完之后,我们就要在自己的blog上进行修改了 。根据上面的实现原理,我们首先需要找到自己的blog的生成menu的代码,然后设置跟ul的id。搞定之后我们就可以直接使用menu.js了。
查找自己的菜单代码:
我们首先打开主题目录下的header.php文件,发现里面内容很少,没有menu的生成代码,但是有这么一句:
get_template_part( 'template/header' );
这就提示我们template下的header文件里面可能有代码,我们打开来看下:
<div id="header"> <div class="navbar container"> <div class="navbar-inner"> 。。。。 。。。。 <ul class="nav"> <?php if ( has_nav_menu( 'top_nav_menu' ) ) { wp_nav_menu( array('theme_location' => 'top_nav_menu', 'container' => '','depth' => 2 ,'items_wrap' => '%3$s' ) ); } else { wp_list_categories('depth=2&title_li=0&orderby=id&show_count=0&number=6'); } ?> 。。。。 。。。。 </div>
在这里我们可以发现一些含有menu的函数调用,通过google我们知道这就是menu的html代码生成位置。
注意:不同的主题文件menu的代码生成位置可能不一样,需要视情况而定。
找到之后我们发现我们的blog的menu代码和demo的不同,怎么办呢,先不管它。我们直接来看生成之后的html,在网页上点击右键,选择查看源代码,找到menu的位置。我这里吧代码贴出来,先看demo的:
<!-- 分类菜单 START --> <div id="menubar"> <ul id="menus" class="menus"> <li class="current-cat"><a title="Home" href="../">All demos</a></li> <li class="cat-item cat-item-40"><a href="javascript:void(0);" title="View all posts filed under .Net">.Net</a> <ul class="children"> 。。。。 <li class="cat-item cat-item-43"><a href="javascript:void(0);" title="View all posts filed under C#">C#</a></li> </ul> </li> <li class="cat-item cat-item-50"><a href="javascript:void(0);" title="View all posts filed under Java">Java</a> <ul class="children"> 。。。。 <li class="cat-item cat-item-56"><a href="javascript:void(0);" title="View all posts filed under Struts">Struts</a></li> </ul> </li> <li class="cat-item cat-item-60"><a href="javascript:void(0);" title="View all posts filed under Web">Web</a> <ul class="children"> 。。。。 <li class="cat-item cat-item-64"><a href="javascript:void(0);" title="View all posts filed under JavaScript">JavaScript</a></li> </ul> </li> </ul> </div> <!-- 分类菜单 END -->
再看下我们自己的blog的:
<ul class="nav"> <li id="menu-item-86" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-86"><a href="http://116.62.110.235/blog/category/coding/">编程</a> <ul class="sub-menu"> 。。。。 <li id="menu-item-248" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-248"><a href="http://116.62.110.235/blog/category/coding/quicknote/">随手记</a></li> </ul> </li> <li id="menu-item-172" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-172"><a href="http://116.62.110.235/blog/category/design/">设计</a> <ul class="sub-menu"> 。。。。 <li id="menu-item-552" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-552"><a href="http://116.62.110.235/blog/category/design/tools/">小工具</a></li> </ul> </li> <li id="menu-item-222" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-222"><a href="http://116.62.110.235/blog/category/operationsystem/">操作系统</a> <ul class="sub-menu"> 。。。。 <li id="menu-item-223" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-223"><a href="http://116.62.110.235/blog/category/operationsystem/linux-ops/">linux</a></li> </ul> </li> </ul>
代码比较多和繁杂,但是通过对比我们可以发现,两者的结构非常相似,只是我们的代码的跟ul没有id,所以我们可以得出,我们自己的header.php文件和demo的虽然有较多不同,但是生成的menu代码却类似,因此,我们只需要稍微修改下自己的header.php文件,让它生成的menu的根ul有id即可。修改如下,将
<ul class="nav">
改为:
<ul id="menus" class="nav">
就OK了。
然后我们就可以仿照demo,在自己的blog的header.php里加上一句:
<!-- 加载菜单效果的 JavaScriot --> <script type="text/javascript" src="<?php bloginfo('template_url'); ?>/js/menu.js"></script>
别忘了把demo的js文件拷贝到我们自己的服务器里。
由于我们的menu的样式和demo不同,因此style.css就不需要进行仿制了,理论上来说这样就可以实现淡入淡出了。但是我们刷新页面后可以发现没有效果。这里就需要分析下原因了。注意,此处的无效的原因是作者使用的模板遇到的,其他的模板如果无效,则需要具体分析。
无效的原因:
我们一共修改了两处代码,现在来看下它们有没有效果。
还是查看页面源代码,定位到menu的部分,发现menu的根ul已经设置了id。
2)查看js有没有生效:
查看页面源代码,我们发现了问题,代码如下:
<meta charset="UTF-8" /> <title>cstriker1407的笔记本</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="profile" href="http://gmpg.org/xfn/11" /> <link rel="pingback" href="http://116.62.110.235/blog/xmlrpc.php" /> <!-- 加载菜单效果的 JavaScriot --> <script type="text/javascript" src="http://116.62.110.235/blog/wp-content/themes/zalive/js/menu.js"></script> <script type="text/javascript"> window.onload = function(){ prettyPrint(); } </script>
原来,我们的模板也用到了window的onload函数,这样就造成了冲突,作者的解决办法是:
1)修改menu.js,注释掉window.onload函数:
/* //由于cstriker1407的主题中已经使用了 window.onload 函数,为了避免冲突,cstriker1407注释掉这里的代码,改为在head.php中,在生成menu代码之后,手动调用MenuList window.onload = function(e) { new MenuList('menus', 0.9); } */
2)在header.php文件中,menu代码生成之后,手动调用js函数:
<ul id="menus" class="nav"> <?php if ( has_nav_menu( 'top_nav_menu' ) ) { wp_nav_menu( array('theme_location' => 'top_nav_menu', 'container' => '','depth' => 2 ,'items_wrap' => '%3$s' ) ); } else { wp_list_categories('depth=2&title_li=0&orderby=id&show_count=0&number=6'); } ?> </ul> <script type="text/javascript"> new MenuList('menus', 0.9); </script>
修改到这里之后,发现淡入淡出效果已经出来了,但是在作者的主题上位置有问题,需要继续更改。
由于在作者的主题上位置显示有问题,这里需要修改下menu.js文件,具体为注释掉会影响位置的代码,仅使js能够更改visibility:
。。。。 。。。。 // 定义初始样式 this.util.setStyle(this.body, 'visibility', 'hidden'); //由于cstriker1407的主题中菜单的位置已经固定,所以只需要对visibility进行修改即可。 // this.util.setStyle(this.body, 'position', 'absolute'); // this.util.setStyle(this.body, 'overflow', 'hidden'); // this.util.setStyle(this.body, 'display', 'block'); 。。。。 。。。。 // 定义激活时样式 //由于cstriker1407的主题中菜单的位置已经固定,所以只需要对visibility进行修改即可。 // this.util.setStyle(this.body, 'left', left + 'px'); // this.util.setStyle(this.body, 'top', top + 'px'); this.util.setStyle(this.body, 'visibility', 'visible'); this.util.setStyle(this.body, 'opacity', this.opacity); this.util.setStyle(this.body, 'filter', 'alpha(opacity=' + this.opacity * 100 + ')');
修改好之后,我们刷新下页面,效果就出来了。注意刷新页面需要使用【 shift + F5 】,强制浏览器重新获取页面,防治js缓存。
到了这一步之后,淡入淡出效果总算是在作者的页面上出来了,真是一部血泪史~
发表评论