如何做网站推广最有效/网站优化方案模板
function startScroll(){if(document.getElementById(“imgscroll”).scrollLeft …
图片水平滚动效果
清华大学教材上的制作网页图片水平滚动
的一个小实验,
自己做了,
但是,
起先没弄懂,
后来结合着页面效果反复看代码,
终于弄明白了一点,
这里和大家分享一下,
先说重点,
网上有说:元素.scrollLeft
是获取滚动条到元素左边的距离
,
这句话太难理解了,
也不准确,
不要以滚动条
为参照物
我个人认为,
应该说:获取的是"元素内的图片向左滚动了一段距离后,此时图片的左边left所在的位置与滚动条所属窗口的左边框之间的距离"
更容易理解,
请注意,
这种说法中出现了"滚动条"
,
那是因为将元素的水平溢出
设置成了overflow-x:scroll
,
overflow-x: scroll
这时才有滚动条的事,
而我们这个例子中,
溢出
被设置成了隐藏hidden
,
所以就没有滚动条出现,
也就与滚动条没有关系了,
不管溢出overflow
是scroll
还是hidden
也好,
参照物
都选择元素的左边框
是最好的,
其实就是以元素的左边框为起点,
去看图片向左滚出去了多远,
object.scrollLeft
,
字面意思,滚动
-往左边
,
人话就是:让容器里的图片内容
朝左边滚动,
而且
scrollLeft
是个变量,
代码document.getElementById(“imgscroll”).scrollLeft=0
;
已充分说明了它是个变量的事实,
代码给它赋了0
的值,
所以也能以此看出scrollLeft
是个数值型的变量,
那既然是变量,
我们就可以给这个变量赋值,
赋值之后能干什么呢
浏览器就可以按照我们给变量的值,
来让图片向左移动到
距离容器窗口左边框那么远的位置上,
移动的距离是图片左边框到容器窗口左边框之间的长度,
请大家一定要注意,
这里是移动到
而不是又移动了
,
移动到
是绝对定位,
又移动了
是相对位移,
移动到
是不管之前图片的位置在那里,
而是以容器窗口左边框为起点
为参照物,
把图片放到距离容器窗口左边框那么远的地方,
又移动了
是以图片上次所在的位置为起点
为参照物,
再
向左移动多远,
我觉得,
移动到
以容器窗口左边框为起点,
又移动了
是以图片上次的位置为起点,
移动到
与上次图片在什么位置无关,
而与容器窗口左边框有关,
因为参照物是容器的左边框,
又移动了
与上次图片在什么位置有关,
而与容器窗口左边框无关,
也就是在上一次图片所处位置上又向左移动了多远,
参照物是图片上一次的位置,
浏览器browser以容器窗口左边框为起点,
将图片向左移动,
参照物是容器窗口左边框,
因为容器已经设置成{overflow:hidden;}
了,
所以,
那些向左移动溢出容器窗口的图像部分也会被hidden了,
好的,
我们都知道,
软件编程中,
数值型的变量都有初值的,
而且数值型变量的初值是0,
这就是说,
当我们没有手动给scrollLeft
赋值时,
scrollLeft
=0,
浏览器一看scrollLeft
是0,
此时图片的左边框和容器窗口左边框重合,
距离正好也是0
所以也就不会
将图片向左移动
了,
为什么能滚动,
因为,
容器里的内容
也就是图片太大了,
超出了容器的宽度
,
就会有一部分图片内容露在容器外边,
所以就具备了把图片向左移动的条件,
如果容器能轻松的装下整个图片就不具备滚动图片的条件了,
有溢出才有滚动的条件,
没有溢出就不具备滚动的条件,
所以要想让图片滚动起来,
必须让图片的宽度大于容器窗口的宽度,
这里有朋友会说用滚动条也行啊,
其实用滚动条不好,
因为我们想要的是图片循环滚动的效果,
而不是要通过滚动条来看到图像的全部,
所以这里我们没有使用滚动条而是使用overflow:hidden
,
滚动条和隐藏原理是一样的,
object.scrollLeft
使用的前提
:
容器需要设置{overflow:hidden;}
就是把图片的溢出部分隐藏不显示,
另外一点
就是图片宽度必须大于容器的宽度,
也就是必须有溢出才具备滚动的条件,
如果没有溢出容器能完全装下图片也就没有滚动的必要了也就不具备滚动的条件了,
只有具备了上述两个条件,
有溢出+隐藏
才能让图片产生向左滚动的效果,
页面中显示的是图片内容的左半部分
,
因为默认图片都是和装它的爸爸容器左对齐的,
而图片内容的右半
部分因为超出
了容器的宽度所以没有显示在页面中,
不滚动的话,
超出容器宽度的那部分图片内容就不会显示在页面中,也就看不到了,
因为设置了overflow:hidden
嘛,
这里简单举个例子:
假设:
有长度为100px
的一副图,
容器宽度设置成80px
,
那么就有20px
的画面露在容器外边从而没有被页面显示出来,
上面提到了,
object.scrollLeft
使用的前提
:容器需要设置overflow:hidden
,
设置了hidden
的效果是:
图片向左移动,
右边原本被隐藏的图片可以进入容器被页面显示出来,
而图片原本在页面中显示的左半边的内容又被挤出容器从而在容器左边被hidden
了,
这样就产生了,
容器里的内容向左滚动的效果,
右边进,
左边出,
object.scrollLeft
还有另外一个尿性,
它不会让图片往左边无限制的移动,
当图片的右边框进入容器窗口,
也就是图片的右边框与容器窗口的右边框重合时,
图片就不能再向左移动哪怕一个像素了,
因为这时候,
图片所有溢出的部分都进入到了容器里,
没有了溢出也就没有了滚动的先决条件,
为什么就不能继续向左移动了呢,
因为.scrollLeft
被设计出来的目的不是清空
容器中的图片内容,
而是要去通过向左滚动来显示那些因为图片体积太大溢出了容器范围而被hidden
了的图片内容,
也就是说,只有容器右侧存在溢出了容器的图像,
才有将图片向左滚动的条件,
既然没有了溢出部分也就不能继续再滚动了,
那到什么时候就滚不动了呢,
到右边那些原本被hidden
的内容随着向左滚动,
最终全部进入容器被显示出来的时候就再也不能滚动了,
也就是当内容的右边界和容器的右边界重合的那一霎那,
滚动自动停止,
这个我个人的理解是,
能滚起来的原因是容器外面有因溢出而被hidden
了的图片内容
现在图片内容都已经出现了,
再也没有溢出的图片了,
就不具备.scrollLeft
的条件了
有两个特殊情况要说明一下:
①如果元素的图片不能滚动(比如:元素的图片没有溢出),
那么scrollLeft 的值是0
。
没有图片溢出,
就不存在把图片向左移动的条件,
再仔细看发现图片左边界与容器的左边框重合,
图片没有位移,
所以scrollLeft 的值是0
,
②如果给scrollLeft
设置的值超过了有溢出的大个的元素的图片的宽度,
(请注意,这里指的是因为太大产生了溢出的图片)
那么scrollLeft
的值也不会超过元素图片的最大宽度,
即使你命令scrollLeft
继续增加,
scrollLeft
的值它也不会变得比元素图片的宽度还大,
因为,
图片在没有移动之前左边框是与元素窗口左边框重合的,
当让图片向左移动了一个图片宽度的距离后,
等于把图片向左移出了元素窗口,
就相当于把图片放在了元素窗口的外边,
此时图像在左侧,
元素窗口在右侧,
图像在元素窗口的外边,
元素窗口中什么都没有,
这是没有意义的,
所以,
scrollLeft
怎么增加也不会超过图片的宽度,
好了,
接下来,
先看xhtml
代码,
为了更直观更清晰我给简化了相信大家一看就懂,
<div id=“imgscroll”>
<table>
<tr>
<td id=“scroll1”>
<ul>
<li><img src=“1.png”/>
<li><img src=“2.png”/>
</ul>
</td>
<td id=“scroll2”></td>
</tr>
</table>
</div>
对上面的xhtml
制定必要的css
样式:
#imgscroll{width:670px;}
#imgscroll ul{width:680px}
因为ul
里面放的是图片,
ul
的宽度就是图片的宽度,
只有图片的宽度溢出了装图片的容器才能滚动图片,
而ul
在imgscroll
里,
所以让ul
的宽度(680)>imgscroll
的宽度(670),
上完整javascript
代码:
</script>
function startScroll(){
if(document.getElementById(“imgscroll”).scrollLeft<document.getElementById(“scroll1”).offsetWidth)document.getElementById(“imgscroll”).scrollLeft++;
else
document.getElementById(“imgscroll”).scrollLeft=0;
}
var speed3=20;
document.getElementById(“scroll2”).innerHTML=document.getElementById(“scroll1”).innerHTML;
myvar=window.setInterval(“startScroll()”,speed3)
document.getElementById(“imgscroll”).οnmοuseοver=function(){window.clearInterval(myvar)}
document.getElementById(“imgscroll”).οnmοuseοut=function(){myvar=window.setInterval(“startScroll()”,speed3)}
</script>
对上述代码进行精简,
给document.getElementById("imgscroll")
起别名,叫爸爸
,
给document.getElementById("scroll1")
起别名,叫孙子Ⅰ
,
所以document.getElementById("scroll2")
是孙子Ⅱ
,
代码可精简如下:
</script>
functionstartScroll()
{
if(爸爸
.scrollLeft<孙子Ⅰ
.offsetWidth)爸爸
.scrollLeft++;
else
爸爸
.scrollLeft=0;
}
var speed3=20;
孙子Ⅱ
.innerHTML=孙子Ⅰ
.innerHTML;
myvar=window.setInterval(“startScroll()”,speed3)
爸爸
.οnmοuseοver=function(){window.clearInterval(myvar)}
爸爸
.οnmοuseοut=function(){myvar=window.setInterval(“startScroll()”,speed3)}
</script>
先说简单的代码,
myvar=window.setInterval(“startScroll()”,speed3)
爸爸
.onmouseover
=function(){window.clearInterval
(myvar)}
爸爸
.onmouseout
=function(){myvar=window.setInterval
(“startScroll()”,speed3)}
就是,当鼠标悬停在容器imgscroll上时,
暂停(方法是.clearInterval
)图片滚动
当鼠标离开容器imgscroll时,
启动定时器myvar(方法是.setInterval
),
启动定时器的效果是:
每隔20毫秒就去调用一次函数 startScroll()
,
图片开始向左滚动,
函数 startScroll()
的核心语句爸爸.scrollLeft++;
就是让图片动起来的关键,
分析如下:
if (
爸爸
.scrollLeft <孙子Ⅰ
.offsetWidth)
{
爸爸
.scrollLeft++;
}
①
爸爸
.scrollLeft
第一次执行if
语句时这里的scrollLeft
由于没有被赋过值,
所以它具有原始的默认值,
就是0
,
所以爸爸.scrollLeft
,
意思是爸爸
元素中scrollLeft
变量的值,
scrollLeft
=0
,
②
孙子Ⅰ
.offsetWidth
offsetWidth
和scrollLeft一样也是个变量,
浏览器会根据scrollLeft的值去执行一个向左移动图片的动作,
而offsetWidth
仅是告诉浏览器孙子Ⅰ
的宽度
是多少,
③
爸爸
.scrollLeft < 孙子Ⅰ
.offsetWidth
看看
爸爸
元素中scrollLeft
变量
小于
孙子Ⅰ
的图片宽度offsetWidth
么,
④
爸爸
.scrollLeft++
爸爸.scrollLeft++
就是:
爸爸.scrollLeft
=爸爸.scrollLeft
+1
当爸爸.scrollLeft
=0
时if
成立,
第一次调用爸爸.scrollLeft++
这条语句就会给爸爸
元素中scrollLeft
变量赋了新值1
,
此时,
浏览器browser看到了scrollLeft
的值1
后,
立刻执行将图片向左移动的动作,
起点是爸爸
的左边框,
幅度为1px,
此时,
图片的左边框距离爸爸
的左边框1px
这么远,
观众看起来图片向左移动了一个像素,
当第二次调用函数 startScroll()
时,
∵scrollLeft
=1,
∴if
语句成立,
执行爸爸.scrollLeft++
后,
scrollLeft
=2,
此时,
浏览器browser看到了scrollLeft
的值2
后,
立刻执行将图片向左移动的动作,
起点仍是爸爸
的左边框,
幅度为2px,
此时,
图片的左边框距离爸爸
的左边框2px
这么远,
观众看起来图片又向左移动了一个像素,
当第三次调用函数 startScroll()
时,
∵scrollLeft
=2,
∴if
语句成立,
执行爸爸.scrollLeft++
后,
scrollLeft
=3,
此时,
浏览器browser看到了scrollLeft
的值3
后,
立刻执行将图片向左移动的动作,
起点仍是爸爸
的左边框,
幅度为3px,
此时,
图片的左边框距离爸爸
的左边框3px
这么远,
观众看起来图片又向左移动了一个像素,
其实,
这里不用继续研究代码,
只要推导一下就可以了,
因为最终呈现在观众面前的图片滚动是匀速的,
所以,
爸爸.scrollLeft
让浏览器执行的动作是移动到
,
而不是又移动了
的动作,
试想一下,
如果是效果为递增的又移动了
的动作,
那随着scrollLef
自增其值越来越大,
每次浏览器执行该动作的结果是步子越来越大,
比如,
当第50次调用函数startScroll()
时,
scrollLef
的值已经自增到了50
,
浏览器要将图片从上次的位置再向左移动了50个像素,
之前第一次调用函数还是向左移动1个像素的,
而这次一下子就移动了50个像素,
这如果还不明显的话,
我们再假设图片足够长,
当第1000次调用函数startScroll()
时,
scrollLef
的值就已经自增到了恐怖的1000
了,
浏览器要将图片从上次的位置再向左移动了1000个像素,
那这个跨度就太大了,
而且跨度一直在变大,
跨度变化不固定,
那就不是等差数列,
也就不是匀速移动了,
那可不是滚动了,
是飞了,
再回头想想,
如果动作是移动到
就合理了,
每一次浏览器执行将图片移动到
的操作后,
上次操作后图片的位置和本次操作后图片的位置相差1像素,
这样,
观众看起来感觉,
图片向左移动的跨度都是1px
,
这就产生了匀速滚动的效果,
综上所述,
浏览器执行scrollLef
向左滚动的动作,
起点
是固定的,
就是爸爸
的左边框,
每次移动图片的起点都是爸爸的左边框
,
最后,
解释代码
孙子Ⅱ
.innerHTML=孙子Ⅰ
.innerHTML;
孙子Ⅰ.innerHTML
的含义是:
孙子Ⅰ
里全部的xhtml代码,
这就是孙子Ⅰ
<td id=“scroll1”>
<ul>
<li><img src=“1.png”/>
<li><img src=“2.png”/>
</ul>
</td>
它里面实际上只有一个
装着两张图片的ul
,
<ul>
<li><img src=“1.png”/>
<li><img src=“2.png”/>
</ul>
其中,
孙子Ⅰ
是一号单元格,
孙子Ⅱ
是二号单元格,
是一个一行两列
的单元格
孙子Ⅱ
让孙子Ⅱ
有着和孙子Ⅰ
相同长度
的内容,
作用是:
保证两个相邻的单元格中1号单元格
的内容能全部向左滚动出父元素窗口,
就这么简单,
而且,
看起来的效果是:
一号单元格的内容在父元素窗口中向左循环
滚动,
这里的孙子Ⅱ.innerHTML=孙子Ⅰ.innerHTML
是javascript
代码,
其等价的xhtml
代码是:
<td id=“scroll1”>
<ul>
<li><img src=“1.png”/>
<li><img src=“2.png”/>
</ul>
</td>
<td id=“scroll2”>
<ul>
<li><img src=“1.png”/>
<li><img src=“2.png”/>
</ul>
</td>
说白了就是在xhtml
代码中给2号单元格也加上一个带有两张图片的ul
孙子Ⅱ.innerHTML=孙子Ⅰ.innerHTML
只需要运行一次就可以,
以后每次循环调用函数startScroll()
时,
孙子Ⅱ
就已经有了和孙子Ⅰ
一样的内容,
而不需要每次调用函数startScroll()
之前再执行一遍孙子Ⅱ.innerHTML=孙子Ⅰ.innerHTML
if (
爸爸
.scrollLeft<孙子Ⅰ
.offsetWidth)爸爸
.scrollLeft++;
else爸爸
.scrollLeft=0;
至此,
我们从全局来看一下,
图片是怎么向左滚,动起来的,
①
我们有1个一行两列的表格,
其中的两个单元格具有相同宽度的内容,
为680px宽度的图片,
比表格的父元素的宽度670px要大出10px,
所以,
不管是两个单元格的总宽度680*2=1360px也好,
还是每个单元格的宽度680px也好,
相对于父元素的宽度670px来说,
都有图片内容溢出,
就具备了scrollLeft
向左滚动的基本条件,
②
当两个单元格具有相同宽度的内容后,
开始调用函数 startScroll()
,
③
函数 startScroll()
首先去调取scrollLeft
的值来查看图片左边框当前所在的位置距离其父元素document.getElementById("imgscroll")
的左边框有多远,
判断这个距离是否超过了图片的宽度,
如果没有超过图片的宽度,
说明图片仍有一部分还在其父元素中,
如果这个距离不小于也就是正好等于图片的宽度值时,
说明这个图片正好挪出了其父元素,
这样就完成了一次让图片从其父元素左边框为起点开始向左滚动直至完全滚出其父窗口的操作,
要想开始下一次滚动,
就需要将图片复位,
也就是把图片重新放回其父元素中,
使用代码
document.getElementById(“imgscroll”)
.scrollLeft=0
;
给scrollLeft
赋0
值,
浏览器会根据这个0
值将图片左边框与其父元素左边框对齐完成图片复位的操作,
也就是将图片左对齐放进其父元素中,
④
接下来,
经过判断if
语句成立,
scrollLeft
自增加一,
浏览器将根据scrollLeft
自增后的新值1px
将图片放置到,
距离其父元素左边框一个像素这么远处,
达到图片向左移动了一点的视觉效果,
如此往复,
图片开始向左滚动,
⑤
以上四步提到的图片指的是第一个单元格
中的图片,
不要忘记我们一共弄了两个单元格,
接下来讲一下为什么要弄两个单元格,
随着第一个单元格
中的图片不断向左移动,
终究会出现第一个单元格
中的图片原本溢出的部分全部向左滚动进父元素里的结果,
这时如果没有第二个单元格的图片接着,
滚动就会立即停止,
所以第二个单元格的目的就是为了保证第一个单元格
中的图片可以一直向左滚动直至其完全滚出父元素,
而为了让观众有图片是循环滚动的效果,
所以,
我们使用javascript
代码
孙子Ⅱ
.innerHTML=孙子Ⅰ
.innerHTML;
这么做让第二个单元格也有和第一个单元格
同样的图片,
看起来就是图片从父元素左边框消失之后,
又从父元素的右边框出现的循环滚动效果,
⑥
其实,
在第一个单元格
的图片的溢出部分完全进入父元素之前,
父元素中只有第一个单元格
的图片的左半部分,
右半部分处于溢出状态,
当第一个单元格
的图片溢出部分完全进入父元素的时候
下一秒开始,
第二个单元格的图片就跟着进入父元素了,
此时父元素中有两个内容,
即,
在第一个单元格
的图片向左完全滚出父元素之前,
父元素中有两个内容,
一个是第一个单元格
的右半边图片,
一个是第二个单元格的左半边图片,
直到,
第一个单元格
的图片完全滚出父元素时,
父元素中才完全是第二个单元格的图片左半边,
第二个单元格图片的右半边也处于溢出状态,
但这种父元素中完全是第二个单元格的图片的情况只持续了一刹那,
此时,
虽然第二个单元格的图片还有溢出,
按理说应该继续向左滚动第二个单元格的图片才对,
但因为第一个单元格
的图片完全滚出父元素时已经触发了else
语句,
此时if
语句判断条件已不成立,
document.getElementById("imgscroll").scrollLeft
已经不小于document.getElementById("scroll1").offsetWidth
了,
这时候不会把第二个单元格的图片继续向左滚动,
而是会立即执行,
将第一个单元格
的图片复位的操作,
document.getElementById(“imgscroll”)
.scrollLeft=0
;
所以,
从下一秒开始,
继续向左滚动的是第一个单元格
的图片,
此时,
父元素中只有第一个单元格
的图片的左半部分,
因为第一个单元格
的图片的右半部分还处于溢出状态,
⑦
由此,
我们也可以看出,
不管是第一个单元格的图片宽度也好,
还是第二个单元格的图片宽度也好,
都应该要比父元素的宽度大,
这样才能有溢出的部分,
才具备继续滚动的条件,
而实际上,
我们的代码是让两个单元格具有相同宽度的相同的内容,
所以,
设置第一个单元格的内容宽度也就是在设置第二个单元格的内容宽度,
所以要想让第一单元格的图片完全滚动出父元素,
第二单元格的图片宽度就要宽于父元素的宽度,
这样才能以第二单元格的图片有足够多的溢出部分来保证第一单元格的图片能够滚出父元素,
第二单元格向一直具备左滚动的条件,
这些溢出部分足够撑到第二单元格的图片向左滚动到达左对齐父元素,
也就是第一单元格图片滚出父元素,
从而触发else
重置第一单元格图片的语句,
至此,
关于图片向左滚动效果的代码,
xhtml
,javascript
,css
都已介绍完毕,
上述内容都是个人的理解和想法,
不妥之处还请诸位不吝赐教,
也欢迎留言探讨,
done.
January22th2021friday