JS轮播图效果实现
轮播图可以说是一种最常见的网页效果了,很多大大小小的网站上都有,它可以以动态的方式向用户展示产品或者别的什么东西。
现在尝试自己实现一个,功能点大致如下:
<div> <a href='javascript:void(0);'><img id='img' src='images/1.jpg'/></a> <ul id='nav-triggers'> <li class='active'>1</li><li>2</li><li>3</li><li>4</li><li>5</li> </ul> </div>
轮播的实现需要用到js间歇调用。一般不适用setInterval,因为它存在一些问题,例如两次轮询有可能并不是互斥执行的等等。这里适用setTimeout的方式实现,结构如下:
code2
// 定时循环调用 var interval = 1500; var func = function(){ console.log('time out'); }; setTimeout(function(){ func(); setTimeout(arguments.callee, interval); }, interval);
定义一个index变量标识当前轮播索引,然后 func 函数体变换一下,就可以实现最简单的轮播
code3
var func = function(){ if(++index > 5) index = 1; // _$,根据id获取dom _$('img').setAttribute('src', 'images/' + index + '.jpg'); };
加上鼠标移入移出导航条的控制
code4
// 定时循环调用 var interval = 3000, // 每隔3秒切换一次 index = 1; // 当前所轮播的索引 // 'nav-triggers'是导航条ul的id var navTriggers = _$('nav-triggers'); var childLis = getChildNodes(navTriggers, 'LI') var changePic = function(idx){ var tween = new Tween(); tween.setup(0.4,1,400); var isImgSeted = false; tween.move(function(cur){ _$('img').style.opacity = cur; if(!isImgSeted){ // _$,根据id获取dom _$('img').setAttribute('src', 'images/' + idx + '.jpg'); isImgSeted = true; } }); addClassName(childLis[idx - 1], 'active'); }; var func = function(){ removeClassName(childLis[index - 1], 'active'); if(++index > 5) index = 1; changePic(index); }; var timeoutObj = setTimeout(function(){ func(); timeoutObj = setTimeout(arguments.callee, interval); }, interval); var isCleared = false; navTriggers.addEventListener('mouseover', function(e){ var target = e.target || e.srcElement; if(target.tagName !== 'LI') return; for(var i=0, len=childLis.length; i<len; i++){ if(target === childLis[i]) break; } clearTimeout(timeoutObj); isCleared = true; if(i == index-1) return; removeClassName(childLis[index - 1], 'active'); index = i+1; changePic(index); }); navTriggers.addEventListener('mouseout', function(e){ if(!isCleared) return; isCleared = false; timeoutObj = setTimeout(function(){ func(); timeoutObj = setTimeout(arguments.callee, interval); }, interval); });
要点1:
图片轮播的控制点用index变量控制。当图片要切换时,先清除掉index(变换前的)对应的列表项(li)的active class。
然后变换index,自增1或者用户选了导航条后,取导航条的当前值。
最后通过index执行图片变换逻辑changePic。
由于这三个逻辑总是要绑在一起操作的,因此封装成函数可能是更好的方式。同时index的变换方式是不确定的,这或许可以通过传入一个返回目标index的函数来解决。当然,现在没有这么做。
要点2:
getChildNodes函数是获取指定元素的指定标签名对应的所有子节点,以数组的形式返回。之所以定义它,是因为在实际测试时发现ul的子节点并不全是li,在开头和最后居然是一个text节点,内容是回车符号(我勒个去,这都可以),这应该是编写html的方式所导致的了。应该可以通过修改html代码解决这个问题,但因为它太充满不确定性了,所以还是写个函数保险点。
function getChildNodes(element, tag){ var childNodeArr = []; for(var i=0, len=element.childNodes.length; i<len; i++){ if(tag === element.childNodes[i].tagName) childNodeArr.push(element.childNodes[i]); } return childNodeArr; }
要点3:关于一些判断
在ul的鼠标移入事件增加了目标是否为li的判断。这是因为目标有可能是ul本身。isCleared标识由鼠标移入和移出公用。鼠标移入时清空了间歇调用后,isCleared才设为true,鼠标移出时,只有isCleared为true,才重新设置间歇调用。
完整代码请参阅附件。