分享
 
 
 

不间断滚动图片Javascript特效讲解

王朝html/css/js·作者佚名  2008-11-25
窄屏简体版  字體: |||超大  

转自:蓝色理想 作者:yaohaixiao

演示地址: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的方法,大家还是需要不断的学习,可能才能完全明白和掌握,我这里不可能一一都讲清楚。好了,收工!

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有