解决思路:
要使层能随滚动条的滚动而滚动,首先必须捕获到滚动条的滚动事件,或者设置一个计时器,不断检索滚动条的滚动位置,然后设置层的坐标值。
具体步骤:
方法一:用onscroll事件触发函数,设置层的坐标。
<div id="oLayer" style="position:absolute;left:30;top:60;z-index:2;background:green;width:120px;height:70px">
</div>
<script>
document.write(new Array(100).join("<br>"))
var init_pos=oLayer.style.posTop
document.body.onscroll=function(){
oLayer.style.posTop=document.body.scrollTop+init_pos
}
</script>
核心代码解释:
(1)
document.write(new Array(100).join("<br>"))
这个是为了观看效果,插入99个<br>换行的代码,在实际应用时可以删掉。
(2)
var init_pos=oLayer.style.posTop
初始化变量init_pos为层oLayer的Y坐标值,posTop和pixelTop取到的值是纯数字,而top取到的是带"px"单位的字符串。可以运行下面的代码来了解一下三个属性的值的数据类型。
<div id="oLayer" style="position:absolute;left:30;top:60;">
<button onclick=’with(oLayer.style)alert("posTop:"+posTop+"\tType:"+typeof(posTop)+"\n\npixelTop:"+pixelTop+"\tType:"+typeof(pixelTop)+"\n\ntop:"+top+"\t\tType:"+typeof(top))’>点击我看结果</button>
</div>
(3)
document.body.onscroll=function(){
oLayer.style.posTop=document.body.scrollTop+fixpos
}
这个是在文档区域拖动滚动条时执行的函数,第二行是重新设置层oLayer的Y坐标,document.body.scrollTop等于滚动滑块上端离滚动的开始点的距离,如果理解不了可以在运行一下下面的代码后单击按钮测试。
<body onload="init_pos=oLayer.style.posTop" onscroll="oLayer.style.posTop=document.body.scrollTop+init_pos">
<div id="oLayer" style="position:absolute;left:30;top:60;">
<button onclick=alert(document.body.scrollTop)>点击查看document.body.scrollTop的值</button>
</div>
<script>
document.write(new Array(100).join("<br>"))
</script>
(4)
oLayer.style.posTop=document.body.scrollTop+fixpos
整句的意思就是设置层oLayer的Y坐标为文档区域的滚动条已滚动量加上层的原Y轴坐标值之和。
方法二:不知道读者有没有注意到,层oLayer的移动很突然,没有平滑移动的过程,立刻就跳到目标位置。再看看下面的代码运行效果:
<div id="oLayer" style="position:absolute;left:30;top:60;z-index:2;background:green;width:120px;height:70px">
</div>
<script>
document.write(new Array(100).join("<br>"))
//初始化变量init_pos为层oLayer的Y坐标值
var init_pos=oLayer.style.posTop
//文档区域滚动时执行scrollit()函数
document.body.onscroll=function scrollit(){
//层要移动到的目标坐标
var target_pos=document.body.scrollTop+init_pos
var step=5 //变量step为步长,层每次移动的距离量
//如果是往上拉滚动条,步长应为负值
if(oLayer.style.posTop>target_pos) step*=-1
oLayer.style.posTop+=step //层的Y坐标值增加
//判断层的当前Y坐标值跟目标距离间的值是否大于一个定值,是的话在50毫秒后继//续执行一次scrollit()函数,否则层停止在当前位置
if(Math.abs(oLayer.style.posTop-target_pos)>Math.abs(step)) setTimeout("scrollit()",50)
}
</script>
方法三:相对之下,层的第二种移动方式比第一种来得平滑一点,但仍然不够自然,下面再看看第三种效果。
<div id="oLayer" style="position:absolute;left:30;top:60;z-index:2;background:green;width:120px;height:70px">
</div>
<SCRIPT>
//输出99个<br>
document.write(new Array(100).join("<br>"))
//变量init_pos为层的最初Y坐标值,last_pos为层最后一层移动后的Y坐标值,在下面的函数执行之前它们是相等的
var init_pos=last_pos=oLayer.style.posTop
/*setInterval(表达式或函数,时间)的作用是每隔一段时间(单位:毫秒)之后执行一次表达式或函数,这里是每1毫秒(千分一秒)执行一次函数*/
setInterval(function(){
//目标坐标,上两段代码里解释过具体意思了
var target_pos=document.body.scrollTop+init_pos
/*步长,目标位置减上一次移动后的位置的十分一(10是经验数字,换成其它值的话效果会产很远),因为last_pos是不断接近target_pos的,所以step的绝对值也越来越小,这就是产生弹性移动的原因。最后"|0"的意思是把前面的计算结果跟0进行二进制的按位“或”运算,作用等同于Math.floor(),只是效率更高*/
var step=(target_pos-last_pos)/10|0
//以step为步长移动层
oLayer.style.posTop+=step
//更新变量last_pos的值,没有这步也不可能产生弹性移动效果
last_pos+=step
//这里的1是1毫秒
},1)
</script>
注意:本例代码只适用于IE浏览器。如果没有特别说明,关于鼠标位置判断和层的相关效果(手写的代码),都是只能运行于IE内核的浏览器。
特别提示
本例的三种方法中,第一种方法代码比较简单,但运动效果非常生硬,直接跳到目标位置;第二种方法稍好一点,层是匀速移动的;第三种方法效果比较好,模拟真实的物体运动,具有运动缓冲的效果,但因为用了setInterval方法,比较耗系统资源。
特别说明
本例的重点在于用onscroll捕获滚动条的滚动事件,并用document.body.scrollTop获取滚动条滚动的距离,最后设置层的posTop和posLeft属性,还有一个非常有用的缓冲运动的实现。
onscroll 当用户滚动对象的滚动条时触发。
scrollTop 设置或获取位于对象最顶端和窗口中可见内容的最顶端之间的距离。
posTop 设置或获取以 top 标签属性指定的单位的对象上方位置。
posLeft 设置或获取以 left 标签属性指定的单位的对象左侧位置。