好记性不如铅笔头

javascript, php, vps && wordpress, web, 编程

WordPress 淡出淡入导航菜单

最近在学习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就不需要进行仿制了,理论上来说这样就可以实现淡入淡出了。但是我们刷新页面后可以发现没有效果。这里就需要分析下原因了。注意,此处的无效的原因是作者使用的模板遇到的,其他的模板如果无效,则需要具体分析。

无效的原因:

我们一共修改了两处代码,现在来看下它们有没有效果。

1)查看menu的id有没有设置:

还是查看页面源代码,定位到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>

 修改到这里之后,发现淡入淡出效果已经出来了,但是在作者的主题上位置有问题,需要继续更改。

3)修改menu.js文件:

由于在作者的主题上位置显示有问题,这里需要修改下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缓存。

到了这一步之后,淡入淡出效果总算是在作者的页面上出来了,真是一部血泪史~

发表评论

12 − 6 =

此站点使用 Akismet 来减少垃圾评论。了解我们如何处理您的评论数据