不间断滚动图片Javascript特效讲解教程
我很久前在YAHOO上扣的代码,兼容性很好,在Windows下的主流浏览器中可以正常运行。
演示地址:index.html
代码下载:scrollpic.rar
大家先不要急着下载代码,你随时都可以下,我们来分析下代码(代码中我已经写了很详细的注释),要之其所以然,在解读别人的代码中学习提高自己,然后可以灵活运用,这个才是我将这个效果贴出来的主要目的,代码如下:
scrollver.js
| scrollVertical.prototype.scrollArea=null; // 滚动的区域 scrollVertical.prototype.scrollMsg=null; // 要滚动的内容 scrollVertical.prototype.unitHeight=0; // 单独一行滚动内容的高度(程序中通过过的要滚动行的一个节点的offsetHeight获得) scrollVertical.prototype.msgHeight=0; // 整个滚动内容的高度 scrollVertical.prototype.copyMsg=null; // 复制滚动内容(程序中使用复制scrollMsg.innerHTML来获得的) scrollVertical.prototype.scrollValue=0; // 滚动的值 scrollVertical.prototype.scrollHeight=0; // 滚动高度 scrollVertical.prototype.isStop=true; // 停止滚动 scrollVertical.prototype.isPause=false; // 暂停滚动 scrollVertical.prototype.scrollTimer=null; // 滚动计时器 scrollVertical.prototype.speed=2000; // (默认)滚动的时间间隔2秒 /** * @method isMoz - 判断是否为Mozilla系列浏览器 */ scrollVertical.prototype.isMoz = function(){ return navigator.userAgent.toLowerCase().indexOf('gecko') > 0; }; /** * @method play - 滚动信息的处理方法(函数) * @param {Object} o - 滚动类 */ scrollVertical.prototype.play = function(o){ var s_msg = o.scrollMsg; var c_msg = o.copyMsg; var s_area = o.scrollArea; var msg_h = o.msgHeight; var anim = function(){ // 如果已经开始计时(间隔时间执行向上滚动), // 就停止它(以免无限制执行,耗系统资源)。 if (o.scrollTimer) { clearTimeout(o.scrollTimer); } // 如果暂停了滚动(鼠标放到了滚动层上) // 开始以10毫秒的时间间隔运行滚动 if (o.isPause) { o.scrollTimer = setTimeout(anim, 10); return; } // 当显示完所有信息后(这时滚动的距离就等于要滚动信息的高度msg_h) // 这时又重新开始滚动,将滚动距离清零 if (msg_h - o.scrollValue <= 0) { o.scrollValue = 0; } else { o.scrollValue += 1; o.scrollHeight += 1; } // 根据浏览器的不同,处理滚动 if (o.isMoz) { // Mozilla引擎浏览器 s_area.scrollTop = o.scrollValue; } else { // 其余的浏览器则使用控制CSS样式处理滚动 s_msg.style.top = -1 * o.scrollValue + "px"; c_msg.style.top = (msg_h - o.scrollValue) + "px"; } // 滚动高度等于显示滚动区域高度时(滚动完一行,一行内容全部显示) // 暂停4秒中,然后再开始执行下依次滚动。 if (o.scrollHeight % s_area.offsetHeight == 0) { o.scrollTimer = setTimeout(anim, o.speed); } else { // 在两行内容之间过度滚动时,每10豪秒上升1px o.scrollTimer = setTimeout(anim, 10); } }; // 执行滚动 anim(); }; /** * scrollVertical 垂直滚动的构造函数 * @param {Object} disp - 必须 显示滚动区域的DOM节点(或节点ID) * @param {Object} msg - 必须 被显示的信息的DOM节点(或节点ID) * @param {string} tg - 可选 以什么标记为一行的标签名称(tagName) */ function scrollVertical(disp, msg, tg){ // 给在之前定义的this.scrollArea付值 if (typeof(disp) == 'string') { // 如果disp给的是节点的ID,通过document.getElementById获取该节点 // 然后付值给this.scrollArea this.scrollArea = document.getElementById(disp); } else { // 如果是DOM节点,直接付给this.scrollArea this.scrollArea = disp; } // 以给this.scrollArea相同的方法给this.scrollMsg付值 if (typeof(msg) == 'string') { this.scrollMsg = document.getElementById(msg); } else { this.scrollMsg = msg; } // 为了开发方便, // 不用一直写this.scrollMsg这么常的名字, // 将两个对象付给局部变量 var s_msg = this.scrollMsg; var s_area = this.scrollArea; // 如果没有给定一行的识别标签, // 默认将li标签认为是一行的标签 // 所以上面介绍的,tag参数是可选的 if (!tg) { var tg = 'li'; } // 获取单行的高度 // 获取到第一(s_msg.getElementsByTagName(tg)[0])tg(一行的标签)的高度,作为单行的高度 this.unitHeight = s_msg.getElementsByTagName(tg)[0].offsetHeight; // 获取整个信息框的高度 // 公式为 单行高度(unitHeight)*行数(s_msg.getElementsByTagName(tg).length,显示信息中包含多少个tg(行)标签) this.msgHeight = this.unitHeight * s_msg.getElementsByTagName(tg).length; /* * 复制要显示的信息: * 连续滚动的实现其实就是通过复制信息, * 并将复制的信添加到原始信息后 * 当原始信息滚动显示完成,就接着滚动显示复制的信息 * 但给人的错觉是,我们看到信息连续不断的显示 */ // 创建复制内容节点 var copydiv = document.createElement('div'); // 这个地方感觉有点嵌妥 // 直接使用element.id的方式,不过看上去,主流的浏览器都支持 // 标准的DOM Core方法: // copydiv.setAttribute('id',s_area.id + "_copymsgid") copydiv.id = s_area.id + "_copymsgid"; // 复制原始的信息 // 将原始的信息s_msg中的内容,直接用innerHTML写到 copydiv.innerHTML = s_msg.innerHTML; // 设置复制信息节点的高度 copydiv.style.height = this.msgHeight + "px"; // 将复制节点添加到原始接点(scrollMsg)后 // 其实实现的方法就是将复制信息节点(copydiv)添家到显示区域的节点(scrollArea)中 s_area.appendChild(copydiv); this.copyMsg = copydiv; // 开始执行滚动方法 this.play(this); } |
我在脚本的注释中已经说了这个效果的实现原理,而实现一个效果的关键就是在于运用setTimeout方法和clearTimeout方法。
setTimeout(func,time)
setTimeout是window对象的一个方法,所以如果要是看到这么写window.setTimeout你不要感到奇怪,我们平时一般都省略了window。
setTimeout方法接受两个参数:
func - 在指定时间间隔内要执行的函数;
time - 执行函数的时间间隔(以毫秒为单位,1000毫秒等于1秒)
我一开始没有解释setTimeout的功能,而是先说了两个参数的意思,我想大家看了后就会有所了解,setTimeout的功能就是:设置定时器,在一段时间之后执行指定的代码。
不如本例中的:
| setTimeout(anim, o.speed); |
也许你有看过类似的写法:
| function dosomething(){ // do something } setTimeOout('dosomething',1000); |
个人建议不要这么写,是这样的代码的可读性太差,虽然也可以正常执行。相信你看到的类似的代码也是很久前的东西了。如果你还在新买的某本书中看到这样的写法,我想你可能很不幸买了本烂书。现在一般我们都这么做:
| function whatWeDoNow(){ var str = 'this is what we do now'; if(doalert) { clearTimeout(doalert) } var doalert = setTimeout(function(){ alert(str); },1000); } |
而且不知道你发现没有,这么写还有一个好处,你的function还可以接受其他的参数,比如这里我们可以接受whatWeDoNow()函数中的局部变量。如果你再结合闭包的使用,好处会更显而易见。
刚才说的一点应该说是一个不好的使用setTimeout的习惯。呵呵,接下来我还要说的一个更不好的使用习惯就是只使用setTimeout()方法,而不使用clearTimeout()方法。
clearTimeout(itimeoutid)
clearTimeout()方法的功能是停止定时器,大家看上面的代码:
| clearTimeout(o.scrollTimer); |
Timer(定时器),够直接吧。那么为什么要停止定时器?什么时候停止呢?
为什么要停,我想用个反问:能一直不停吗,你的机器受得了吗?这里我想应该说说我们使用setTimeout的目的,我们通常使用它来实现像本例这样的动画效果。需要在很短的时间内连续不断的执行定时器,当然它是要占资源的啊。想想,只是不断的创建,而且往往我们做的处理,在1秒中内会执行很多次函数,一两次还好,上百上千次,而且一个复杂些的动画,执行很短的时间内几万次也不是没有可能事情。你想想,如果我们不在每执行完一次后,销毁它。要是再加上定时器执行的函数又是个比较NB点的运算,你的宝贵的系统资源...,呵呵!
所以应该向我给的例子中那样,记得在每次执行了定时器后停止(销毁,释放资源)它。
| function whatWeDoNow(){ var str = 'this is what we do now'; if(doalert) { clearTimeout(doalert); // clear } var doalert = setTimeout(function(){ alert(str); },1000); } if (o.scrollTimer) { clearTimeout(o.scrollTimer); // clear } |
呵呵,其实销毁的方法很简单,就是在每次创建定时器前,判断是否已经创建了订时器,就像特效例子中的
| if (o.scrollTimer) { clearTimeout(o.scrollTimer); // clear } .... .... if (o.scrollHeight % s_area.offsetHeight == 0) { o.scrollTimer = setTimeout(anim, o.speed); } else { o.scrollTimer = setTimeout(anim, 10); } |
逻辑就是:

是不是一个很流畅的循环?现在大家应该知道了,为什么要clearTimeout和何时clearTimeout了吗?
介绍了大半天的setTimeout和clearTimeout,呵呵,现在可以看看怎么使用这个特效吧,页面代码:
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>滚动图片</title> <style type="text/css"> <!-- *{ margin:0; padding:0; } body{ text-align:center; background-color:#FFF; color:#000; font:'宋体',sans-serif; } img{ border:0; } ul,li{ list-style-type:none; } a:link, a:visited{ color:#000; text-decoration:none; } a:hover{ color:#F00; text-decoration:none; } #container{ margin:0 auto; position:relative; margin-top:10px; width:720px; height:100px; overflow:hidden; } #message, #message_copymsgid{ margin:0; width:720px; overflow:hidden; } #container ul{ float:left; width:720px; height:100px; overflow:hidden; clear:both; } #container li{ float:left; text-align:center; width:120px; height:100px; line-height:100px; overflow:hidden; padding:0; } #container li img{ width:96px; height:96px; margin-bottom:10px; padding:1px; border:1px solid #999; } --> </style> </head> <body> <div id="container"> <div id="message"> <ul><li><a href="http://www.yaohaixiao.com/" target="_blank" title="听海"><img src="img/img1.gif" alt="听海" /></a></li> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="听海"><img src="img/img1.gif" alt="听海" /></a></li> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="听海"><img src="img/img1.gif" alt="听海" /></a></li> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="听海"><img src="img/img1.gif" alt="听海" /></a></li> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="听海"><img src="img/img1.gif" alt="听海" /></a></li> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="听海"><img src="img/img1.gif" alt="听海" /></a></li> </ul> <ul> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="宝贝"><img src="img/img2.gif" alt="宝贝" /></a></li> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="宝贝"><img src="img/img2.gif" alt="宝贝" /></a></li> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="宝贝"><img src="img/img2.gif" alt="宝贝" /></a></li> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="宝贝"><img src="img/img2.gif" alt="宝贝" /></a></li> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="宝贝"><img src="img/img2.gif" alt="宝贝" /></a></li> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="宝贝"><img src="img/img2.gif" alt="宝贝" /></a></li> </ul> <ul> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="因为你"><img src="img/img3.gif" alt="因为你" /></a></li> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="因为你"><img src="img/img3.gif" alt="因为你" /></a></li> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="因为你"><img src="img/img3.gif" alt="因为你" /></a></li> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="因为你"><img src="img/img3.gif" alt="因为你" /></a></li> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="因为你"><img src="img/img3.gif" alt="因为你" /></a></li> <li><a href="http://www.yaohaixiao.com/" target="_blank" title="因为你"><img src="img/img3.gif" alt="因为你" /></a></li> </ul> </div> </div> <script type="text/javascript" language="javascript" src="js/event.js"></script> <script type="text/javascript" language="javascript" src="js/scrollver.js"></script> <script type="text/javascript" language="javascript"> <!-- function init_Scroll(){ // 创建一个垂直滚动对象的实例 // 显示容器为container,你也可以直接写document.getElement('container') var scrollPics = new scrollVertical('container','message','ul'); scrollPics.speed = 4000; // 间隔时间,更准确的说,是滚动完一行,停留的时间 scrollPics.isPause = true; // 是否暂停为true,不能一开始就滚动,需要先停留下,然后再滚动 // 这个则是指定,第一次显示滚动内容第一行停留的时间为2秒 // 2秒后isPause为false,也就不暂停滚动,开始滚动了。 // 这个时间大家可以自己设定 var timer_start = setTimeout(function(){clearTimeout(timer_start);scrollPics.isPause = false;},2000); Event.addEvent(scrollPics.scrollArea,"mouseover",function(){scrollPics.isPause = true;}); Event.addEvent(scrollPics.scrollArea,"mouseout",function(){scrollPics.isPause = false;}); } /* * 其实这里也可以直接写init_Scroll(); * 应为我已经把脚本放到文档的最后面, * 在加载脚本之前,所有的DOM节点已经加载完毕 * 已经可以直接用脚本访问DOM节点了 */ Event.addEvent(window,'load',init_Scroll); //--> </script> </body> </html> |
刚才给大家介绍了JS的一些知识点,现在就讲下相关的CSS技巧。
| #container{ margin:0 auto; margin-top:10px; width:720px; height:100px; overflow:hidden; } |
一定要“overflow:hidden;”,为什么?呵呵,看看我们把高度设置为了height:100px;,正好是只一行信息的高度,如果你不overflow:hidden,在firefox也许没有问题,它会严格按照你指定的高度显示相应高度的内容,而隐藏多余的部分(多余的5行),而在IE中,一直就自做聪明把容器挤高,让它把里面的全部内容都显示出来。而我们的效果也是只显示一行,而隐藏多余的5行。
你可能要问了,怎么有多余的5行?呵呵,其实代码中已经解释了:
| // 创建复制内容节点 var copydiv = document.createElement('div'); // 这个地方感觉有点嵌妥 // 直接使用element.id的方式,不过看上去,主流的浏览器都支持 // 标准的DOM Core方法: // copydiv.setAttribute('id',s_area.id + "_copymsgid") copydiv.id = s_area.id + "_copymsgid"; // 复制原始的信息 // 将原始的信息s_msg中的内容,直接用innerHTML写到 copydiv.innerHTML = s_msg.innerHTML; // 设置复制信息节点的高度 copydiv.style.height = this.msgHeight + "px"; // 将复制节点添加到原始接点(scrollMsg)后 // 其实实现的方法就是将复制信息节点(copydiv)添家到显示区域的节点(scrollArea)中 s_area.appendChild(copydiv); |
因为我们又复制了一份信息,并添加到要显示滚动信息的容器中了,所以3行变6行了。
呵呵,接下的也没有什么好讲了,大家看我的注释,应该可以很清楚了。唯一要注意的一点就是这里
| // 滚动高度等于显示滚动区域高度时(滚动完一行,一行内容全部显示) // 暂停4秒中,然后再开始执行下依次滚动。 if (o.scrollHeight % s_area.offsetHeight == 0) { o.scrollTimer = setTimeout(anim, o.speed); } else { // 在两行内容之间过度滚动时,每10豪秒上升1px o.scrollTimer = setTimeout(anim, 10); } |
o.scrollHeight % s_area.offsetHeight == 0,要明白它确切的意思。
| #container{ margin:0 auto; margin-top:10px; width:720px; height:100px; overflow:hidden; } #message, #message_copymsgid{ margin:0; width:720px; overflow:hidden; } #container ul{ float:left; width:720px; height:100px; overflow:hidden; clear:both; } |
ul也就是我们一行的高度为100px,o.scrollHeight已经滚动的高度。呵呵,不知道你发现了问题没有?
对了,问题就在 % s_area.offsetHeight,我之所以没有更正原程序里的这个缺点,是因为如果你不对#container做任何修饰,这么写没有错。因为s_area也就是#container这里我只定义了height:100px;,如果我要是这么写:
| #container{ margin:0 auto; margin-top:10px; width:720px; height:100px; overflow:hidden; border:1px; padding:1px; } |
呵呵,你觉得会有什么结果?这里我就卖个官子,给大家出个作业,看看像我这样做了会,有一个什么结果,还有o.scrollHeight % s_area.offsetHeight == 0要怎么改该呢?
好了,特效讲解完毕,也不知道我这么讲解一个特效,对你有没有帮助。像里面的ceateElement,appendChild等等DOM的方法,大家还是需要不断的学习,可能才能完全明白和掌握,我这里不可能一一都讲清楚。好了,收工!
评论加载中…
作者:warm-ice
作者:puhoo.net
作者:/
作者:/
作者:
您现在的位置:
教程导航




