js运动(二)—— 右侧悬浮框
右侧悬浮框,其视觉效果为:即使滚动条滚动,悬浮框也依然在可视范围内。可以理解为悬浮框跟随滚动条运动。
这个例子看似基础,其实里面集成了很多的知识点,详见下文。
1. 文档坐标和视口坐标
元素的位置是以像素来度量的,向右代表X坐标的增加,向下代表Y坐标的增加。但是,有有个不同的点作为坐标系的原点:元素的X和Y坐标可以相对于文档的左上角后者相对于在其中显示文档的视口的左上角。在顶级窗口和标签页中,“视口”只是实际上显示文档内容的浏览器的一部分;它不包括浏览器的“外壳”(如菜单、工具条和标签页)。针对框架页中显示的文档,视口是定义了框架页的 元素。无论在何何种情况下,当讨论元素的位置时,必须弄清楚使用的坐标是文档坐标还是视口坐标(注意,视口坐标有时也叫做窗口坐标)
如果文档比视口要小,或者说它还未出现滚动,则文档的左上角就是视口的左上角,文档和视口坐标系统是同一个。但是,一般来说,要在两种坐标系之间互相转换,必须加上或减去滚动的偏移量(scroll offset)。例如,在文档坐标中如果一个元素的Y坐标是200像素,并且用户已经把浏览器向下滚动了75像素,那么视口坐标中元素的Y坐标就是125像素[注释1]。同样,在视口坐标中如果一个元素的X坐标是400像素,并且用户已经水平滚动了视口200像素,那么文档坐标中像素的X坐标中元素的X坐标就是600像素[注释2]。
文档坐标比视口坐标更加基础,并且在用户滚动时他们不会发生变化[注释3]。不过,在客户端编程中使用视口坐标是非常常见的。当使用CSS指定元素的位置时运用了文档坐标。
为了在坐标系中转换,我们需要判定浏览器窗口的滚动条的位置。Window 对象的 pageXoffset
和 pageYOffset
属性在所有的浏览器中提供这些值,除了 IE8 及更早的版本以外。IE(和所有现代浏览器)也可以通过 scrollLeft
和 scrollTop
属性来获得滚动条的位置。令人迷惑的是,正常情况下通过查找文档的根节点(document.documentElement
)来获取这些属性,但是在怪异模式下,必须在文档的元素(
documeng.body
)上查询它们。
以上字段摘自《JavaScript权威指南》(P390),个人理解如下。
注释1:
注释2:
注释3:元素会随着文档一起移动。当向下滚动时,元素与文档一起上移;当水平滚动时,元素与文档一起左移,所以其文档坐标并不会改变。
在滚动动作中,动的都是文档(元素随动),视口不会动。所以当定义为视口坐标并伴随滚动时,元素的视口坐标不会改变,而文档坐标会改变;当定义为文档坐标并伴随滚动时,元素的文档坐标不会改变,但视口坐标会改变。
2.关于元素尺寸、位置和溢出的一些信息
2.1 offsetHeight 和 offsetWidth
《JavaScript权威指南》(P393-396)中是这么描述的:任何HTML元素的只读属性offsetWidth 和 offsetHeight 以 css 像素返回它的屏幕尺寸,返回的尺寸包含元素的边框和内边框,除去了外边框。
则如下图。
2.2 clientHeight 和 clientWidth
《JavaScript权威指南》中是这么描述的:clientWidth 和 clientHeight 类似 offsetWidth 和 offsetHeight ,不同的是它们不包含边框大小,只包含内容和它的内边距。同时,如果浏览器在内边距和边框之间添加了滚动条,clientWidth 和 clientHeight 在其返回值中也不包含滚动条。注意,对于类似 、
、
、
这些内联元素,clientWidth 和 clientHeight总是返回0。
则如下图。
2.3 scrollWidth 和 scrollHeight
《JavaScript权威指南》中是这么描述的:scrollWidth 和 scrollHeight是元素的内容区域加上它的内边距再加上任何溢出的尺寸。当内容刚好和内容区域匹配而没有溢出时,这些属性与 clientHeight 和 clientWidth 是相等的。但当溢出时,它们就包含溢出的内容,返回值比 clientHeight 和 clientWidth 要大。
则如下图。
2.4 scrollTop
scrollTop指定元素滚动条的位置,这个属性是可写的。
2.5 offsetLeft 和 offsetTop
所有元素拥有offsetLeft 和 offsetTop属性来返回元素的 X 和 Y 坐标。对于很多元素,这些值是文档坐标,并直接指定元素的位置。但对于已定位元素的后代元素和一些其他元素(如表格单元),这些属性返回的坐标是相对于祖先元素而非文档。
3. 右侧悬浮框
rightFloatingFrame
代码解读:
给文档设置一个高度,使得文档可以出现滚动条。注意,是设置 style 属性 而不是直接设置height属性。
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
在第一节讲过,需要兼容标准模式和怪异模式。
var clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
这句在原教程中没有,原教程中直接使用document.documentElement.clientHeight
,而没有像scrollTop一样做兼容处理,是遗忘还是故意呢?
oDiv.style.top = clientHeight + scrollTop - oDiv.offsetHeight + "px";
因为元素本身绝对定位在bottom为0的地方,使用可视区高度加上溢出高度减掉元素本身的高,就得到元素顶部的坐标。注意不要忘了单位。
简单的代码确实能够做到悬浮的效果,但在滚动条滚动时,悬浮框存在抖动现象。比较可行的解决办法是,让元素缓慢运动到位置而不是直接到位。
这就要用到 js运动(一)— sidebar(分享到)中缓动一节提到的 moveTo 函数了,将 clientHeight + scrollTop - oDiv.offsetHeight
当成iTarget传入函数即可。
扩展:当需要把悬浮框停留在中间而非右下角时,元素的 top 属性的目标值 变成 parseInt(clientHeight - oDiv.offsetHeight ) / 2 + scrollTop );
元素位于中间,则可视区高度减掉元素自身的高度的一半即为元素到上边框或者到下边框的距离,加上溢出部分,即可得到元素的top属性目标值。当然,由于计算可能出现小数,所以使用了parseInt函数将目标取整。
4. 总结
右侧悬浮框的实现整体并不复杂,但本文最大的要点还是在第一节和第二节的知识点上,同时,也相当于复习了一遍缓动的相关知识。
参考文献
【1】《JavaScript权威指南》
【2】智能社:JavaScript教程——从入门到精通 ( https://ke.qq.com/course/152997?taid=766917950461349 )
【3】js运动(一)—— sidebar(分享到)( https://blog.csdn.net/qq_31305965/article/details/89676391 )
标签:
相关文章
-
无相关信息