摘要:而和则表示该容器中页面视图区的大小减去边框宽度。语法实际上,返回的值是一个双精度浮点值,指示文档当前从原点垂直滚动的像素数,其中正值表示向上滚动。除此之外,旧版本不支持这些属性,必须通过检查其他非标准属性来解决。
博客地址:https://guitong.github.io/blo...
上一节中,我们分析了 jQuery lazyload 源码,其中有这么一段:
/* 在jQuery命名空间内定义了便捷的方法,判断图片是否在容器视口范围内 */ $.belowthefold = function (element, settings) {...} $.rightoffold = function (element, settings) {...} $.abovethetop = function (element, settings) {...} $.leftofbegin = function (element, settings) {...} $.inviewport = function (element, settings) {...}
说实话,这才是我最感兴趣的内容。那么实现一个lazyload,应该怎样判断图片与浏览器可见区域的相对位置呢,现在以$.belowthefold方法为例,看一下其实现方式:
$.belowthefold = function(element, settings) { var fold; if (settings.container === undefined || settings.container === window) { fold = (window.innerHeight ? window.innerHeight : $window.height()) + $window.scrollTop(); } else { fold = $(settings.container).offset().top + $(settings.container).height(); } return fold <= $(element).offset().top - settings.threshold; };
首先这段代码的目的是判断当前元素(图片)是否在浏览器视口的下方。
变量fold我理解为当前文档已“折叠”的高度,也就是当前浏览器视口的最底部至文档最顶部的距离。与fold变量值相比较的值是$(element).offset().top - settings.threshold,那么这个值代表什么呢?
seetings.threshold是我们上节提到过的临界值,默认为0,这里我们可以先将其忽略。jQuery对象的offset()方法定义如下:
Get the current coordinates of the first element in the set of matched elements, relative to the documents.
也就是当前元素相对于文档的坐标。它的top值即为元素到文档顶部的距离。
那么也就不难理解,如果这个值大于等于文档已“折叠”的高度值,它的位置就在浏览器视口的下方。
然而这些jQuery方法也是封装过的方法,我们还需要探究它们的实现方式。
一、如何得到浏览器视口(即可见区域)的大小以下内容参考自大红本 — 《JavaScript高级程序设计》,第三版,第八章
跨浏览器确定一个窗口的大小不是一件简单的事。IE9+、Firefox、Safari、Opera和Chrome均为此提供了4个属性:innerWidth 、innerHeight、outerWidth、outerHeight。在IE9+、Safari和Firefox中,outerWidth和outerHeight返回浏览器窗口本身的尺寸(无论是最外层的window对象还是从某个框架访问)。在Opera中,这两个属性的值表示页面视图容器(这里所谓的“页面视图容器”指的是Opera中单个标签页对应的浏览器窗口)的大小。而innerWidth和innerHeight则表示该容器中页面视图区的大小(减去边框宽度)。在Chrome中,outerWIdth和outerHeight与innerWidth、innerHeight返回相同的值,即视口(viewport)大小而非浏览器窗口大小。
IE8及更早版本没有提供取得当前浏览器窗口尺寸的属性;不过,它通过DOM提供了页面可见区域的相关信息。
在IE、Firefox、Safari、Opera和Chrome中,document.documentElement.clientWidth和document.documentElement.clientHeight中保存了页面视口的信息。在IE6中,这些属性必须在标准模式下才有效;如果是混杂模式,就必须通过document.body.clientWidth和document.body.clientHeight取得相同信息。而对于混在模式下的Chrome,则无论通过document.documentElement还是document.body中的clientWidth和clientHeight属性,都可以取得取得视口的大小。
(跑题了?? )
虽然最终无法确定浏览器窗口本身的大小,但却可以取得页面视口的大小,如下所示:
var pageWidth = window.innerWidth, pageHeight = window.innerHeight; if (typeof pageWidth != "number") { if (document.compatMode == "CSS1Compat") { pageWidth = document.documentElement.clientWidth; pageHeight = document.documentElement.clientHeight; } else { pageWidth = document.body.clientWidth; pageHeight = document.body.clientHeight; } }
这段代码很好理解,值得注意的是document.compatMode这个属性。该值表明当前文档的渲染模式为“混杂模式”还是“标准模式”。当值为"CSS1Compat"代表标准规范模式;当值为"BackCompat"代表混杂模式。
二、如果得到文档在在垂直/水平方向滚动的距离这里以垂直方向为例。
先来看一个stackoverflow上的回答,翻译如下:
获取滚动距离的标准方法为window.scrollY。Chrome、Firefox、Opera、Safari及IE Edge(或更高版本)均支持此方法。如果您仅需要支持这些浏览器,使用这个属性即可。
IE >= 9 支持一个类似的属性window.pageYOffset,为了保证兼容性,在现代浏览器中会返回与window.scrollY相同的值,尽管它可能在某些时候被弃用。
使用document.documentElement.scrollTop或document.body.scrollTop的问题是,它们并不是总是都被定义了滚动。例如,Chrome和Safari将滚动定义在元素,而Firefox则定义在了document.documentElement返回的元素上。这不是标准化的,并且在未来版本的浏览器中可能会发生变化。然而,如果scrollY和pageYOffset不存在,则这是获取滚动位置的唯一方法。
遂总结如下:
window.scrollY || window.pageYOffset || document.body.scrollTop + (document.documentElement && document.documentElement.scrollTop || 0)
经过测试,这个方法是可行的。不过,正如文中所说,果然在未来版本的浏览器中发生了变化。在最新的Chrome、Safari、Firefox中测试发现,Chrome与Firefox表现相同,document.documentElement.scrollTop返回滚动值,而document.body.scrollTop返回0,Safari则与它们相反。
再来看一下MDN上对window.scrollY的解释。
window接口的只读属性值scrollY返回文档当前垂直滚动距离的像素值。这个值在现在浏览器中是亚像素精准的,这意味着它不一定是一个整数。您可以从scrollY属性获取文档水平滚动的像素值。
# 语法
var y = window.scrollY实际上,返回的值是一个双精度浮点值,指示文档当前从原点垂直滚动的像素数,其中正值表示向上滚动。如果文档在子像素精准的设备上呈现,则返回的值也是子像素精准的,并且可能包含一个小数分量。如果文档没有向上或向下滚动,则滚动值是 0 。
如果你需要一个整型值,可以使用Math.round()方法
用更技术的话说,scrollY返回当前视口顶边的Y坐标,如果没有视口,则返回 0 。
# 示例
// make sure and go down to the second page if (window.scrollY) { window.scroll(0, 0); // 重置滚动条位置 } window.scrollByPages(1);(这个示例 出现在这里感觉怪怪的)
# 注意事项
使用此属性来检查使用相对滚动方法时(如;scrollBy()、scrollByLines()、scrollByPages())文档是否尚未滚动。
pageYOffset属性是scrollY属性的别名:
window.pageYOffset == window.scrollY // always true考虑到跨浏览器兼容性,使用window.pageYOffset替代window.scrollY。除此之外,旧版本 IE(< 9)不支持这些属性,必须通过检查其他非标准属性来解决。完全兼容的的例子如下:
var supportPageOffset = window.pageXOffset !== undefied; var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat"); var scrollX = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft; var scrollY = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.document.scrollTop : document.body.scrollTop;# 规范
CSS Object Model (CSSOM) View ModuleThe definition of "window.scrollY" in that specification.
==================== 太平洋分割线=======================
那么可以总结一下了。
要获得页面当前的滚动值,window.scrollY是基于标准的方法。然而考虑到跨浏览器兼容性,应该使用window.pageYOffset,该属性是window.scrollY的别名,被绝大多数现代浏览器所支持。对于低版本IE浏览器(< 9),可以判断渲染模式(标准or混杂)来选择使用document.documentElement.scrollTop/Left或document.body.scrollTop/Left方法。
推荐:
var supportPageOffset = window.pageXOffset !== undefined; var isCSS1Compat = ((document.compatMode || "") === "CSS1Compat"); var scrollX = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft; var scrollY = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;三、???
发现跑题了,不是要看一下jQuery方法的源码吗???不过应该大同小异。
明白了上面两个重要的方法,实现一个兼容性良好lazyload就变得轻而易举。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/89441.html
摘要:今天开始带型带秀专题。专题第二节会深入到源码。在可视图片加载后,浏览器将处于就绪状态。只需要将该容器元素作为对象传递。默认地,循环会在找到第一个视口外的图像时停止。但是某些页面的布局不符合该假设。最差的情况是该值为实际图片的数量。 今天开始带型带秀专题 -- Lazy Load。先从使用比较广泛的 jQuery Lazy Load 插件开始,逐步深入。该插件已经开发到了第二版,有兴趣的...
摘要:参考文章使用及源码分析关于插件的基本介绍和使用请看上一篇文章。显示方法默认为,也可以设置为,源码中隐藏了一个配置属性,用于设置动画运行的时间。是否忽略隐藏的元素设置为时会忽略处理隐藏的元素。在触发事件时执行的回调。 参考文章:jQuery.lazyload使用及源码分析 关于 jQuery lazyload 插件的基本介绍和使用请看上一篇文章。(水水一章啦-。-) Overview 让...
摘要:专题系列第十五篇,讲解惰性函数需求我们现在需要写一个函数,这个函数返回首次调用时的对象,注意是首次。解决四惰性函数不错,惰性函数就是解决每次都要进行判断的这个问题,解决原理很简单,重写函数。 JavaScript 专题系列第十五篇,讲解惰性函数 需求 我们现在需要写一个 foo 函数,这个函数返回首次调用时的 Date 对象,注意是首次。 解决一:普通方法 var t; functio...
摘要:初始化我们知道容器初始化后会对容器中非懒加载的,单例的以及非抽象的定义进行的初始化操作,所以我们分析源码的入口也就是在容器初始化的入口,分析容器初始化后在什么地方开始第一次的初始化。 前言 Spring IOC容器在初始化之后会对容器中非懒加载的,单例的以及非抽象的bean定义进行bean的初始化操作,同时会也涉及到Bean的后置处理器以及DI(依赖注入)等行为。对于Bean的初始化,...
摘要:粗读近来没什么特别要做的事,下班回来的空闲时间也比较多,所以抽空看看懒加载是怎么实现的,特别是看了下的库的实现。之先别关注,按他给注释说测试用。之是组件绑定事件时会触发的函数。 react-lazy-load粗读 近来没什么特别要做的事,下班回来的空闲时间也比较多,所以抽空看看懒加载是怎么实现的,特别是看了下 react-lazy-load 的库的实现。 懒加载 这里懒加载场景不是路由...
阅读 830·2021-09-07 09:58
阅读 2684·2021-08-31 09:42
阅读 2861·2019-08-30 14:18
阅读 3089·2019-08-30 14:08
阅读 1835·2019-08-30 12:57
阅读 2761·2019-08-26 13:31
阅读 1302·2019-08-26 11:58
阅读 1055·2019-08-23 18:06