几乎所有的项目都要解决这样一个问题:判断一个元素是否出现在浏览器窗口中?因为通过它我们可以极大的优化项目的性能,进而提升用户的的体验。原生javasxript获取浏览器的滚动距离和可视窗口的高度

使用场景及技术分析

所涉及的业务实现,比较常见的就是电商平台或者是图片展示类的网站。电商网站,如:淘宝京东等;图片展示类,如:花瓣pinterest

涉及的技术,如:lazyload技术动态的加载图片(元素),无限加载技术,包括基于骨架屏技术加载静态资源。

  • 懒加载(lazyload):它目的是按需加载,而很大一部分项目的前端实现是通过判断一个元素是否出现在浏览器窗口中,如果出现则将img元素标签内的src属性中的图片地址替换成自定data-src属性的地址,但这里不一定是data-src属性,也可能是srcsetpinterest中就是这样做的,当然你也可以定义成任何你喜欢的,这只是其中的一种方式;另一种是判断元素是否出现在浏览器窗口中之后,然后加载一个HTML代码块,小米商城官网就是这样实现的,当然也有其他一些也是这样做的,这里就不一一做介绍了。
  • 无限加载(infinte scroll):它是通过底部的 加载更多 这个代码块是否出现在浏览器窗口中,如果在,就向容器代码块中追加一定数量的相关代码块,这时 加载更多 这个代码块就会被挤压出到浏览器窗口之外。当然有些无限加载技术也使用lazyload。
  • 骨架屏技术(skelton screen):这个技术在前一波广受关注,它的原理就是在请求一个页面时,先不显示页面的内容,先显示页面的布局,像文字、图片、视频等静态资源都不显示,而显示的是与页面布局相关的css样式。其实通俗一点来说,就是网页做一个CT,这样是不是理解起来更方便?像淘宝的pc官网,youtube都是这样实现的。

这些业务和技术的目的都是为了为了解决低网速情况下使用web应用,如果页面内内容没有加载,那么就会造成低用户体验。

这些业务和使用的技术基本上都用了 判断页面的元素是否出现在浏览器窗口中

如何判断一个元素是否出现在窗口中呢?

现在通用的是基于浏览器的窗口的判断

那么何为基于浏览器窗口的判断呢?这要通过DOM的API .getBoundingClientRect() ,获取目标元素距离浏览器窗口的位置坐标(top, left) 或者(x, y)坐标,所以说是基于浏览器窗口的。我们可以拖动浏览器的滚动条来使目标元素从浏览器的顶端进入浏览器窗口(这可以判断上边界),也可以从浏览器的底部进入浏览器窗口(这可以判断下边界),而这正好是判断目标元素进入浏览器窗口的边界。

上边界:

目标元素的底边刚好和浏览器的顶部重合,当滚动条向下滚动,目标元素从底部开始一点点的出现,直到目标元素整个出现在浏览器窗口,反之,则逐渐远离。如果目标元素高度大于浏览器窗口的高度,那么浏览器窗口内就不不出现整个目标元素,而只会出现部分,基于这种情况衍生了一种目标元素背景图片的滚动动画。可参考苹果官网

下边界:

目标元素的顶部刚好和浏览器的底部重合,当滚动条向上滚动,目标元素从顶部部开始一点点的出现,直到目标元素整个出现在浏览器窗口,反之,则逐渐远离。

我们可以浏览器的滚动条向下滚动(也可以按照向下滚动,答案类似)写出如下的代码:


var clienRect = el.getBoundingClientRect(); if (clientRect.top > -clientRect.width && clientRect.top < window.innerHeight) {}
// 或者
if (clientRect.bottom > 0 && clientRect.top =< window.innerHeight) {}

有的同学可能会问,是不是窗口的高度小于目标元素的高度,或者窗口的高度大于目标元素的高度都这样都一样呢?我想说一样,因为这里是根据两个边界得出的结论。

上面的判断包括目标元素的部分出现在浏览器窗口,那么如何判断整个目标元素出现在浏览器的窗口中呢?可参考如下的代码:


var clienRect = el.getBoundingClientRect(); if (clientRect.top > 0 && clientRect.top < window.innerHeight - clientRect.width) {}
// 或者
if (clientRect.top >= 0 && clientRect.bottom > window.innerHeight) {}

兼容性可参考can i use

基于document文档的顶部来判断

这里要使用的是DOM元素的 .offsetTop 来计算目标元素的顶部边界到document文档的顶部边界的距离,使用window的 .pageYoffset 来计算当浏览器滚动条滚动时document文档卷起的高度,通过比较这两个高度,我们就可以轻松的判断目标元素是否出现在浏览器窗口内。

当目标元素的上边界和浏览器窗口的下边界重合,目标元素的 offsetTop 是个定值,所以此时document文档卷起的高度和目标元素的 offsetTop 之间存在这样一个等式:window.innerHeight + window.pageYoffset = el.offsetTop。若继续向下滚动浏览器的滚动条,目标元素将出现在浏览器当中,我们都知道 window.pageYoffset 的值将继续变大,由于 el.offsetTopwindow.innerHeight 都是个定值,所以我们可以得到这样一个边界条件,当 window.pageYoffset > el.offsetTop - window.innerHeight ,目标元素从浏览器窗口的底部逐渐出现。

当浏览器的滚动条继续向上滚动会出现目标元素的下边界和浏览器窗口的上边界重合的情况,当继续向下滚动滚动条元素将从浏览器窗口消失,此时存在这样一个等式:window.pageYoffset + el.offsetHeight = el.offsetTop ,所以很明显,如果 window.pageYoffset 的值继续增大,目标元素将消失与浏览器窗口,因此,很明显,只有 window.pageYoffset < el.offsetTop - el.offsetHeight 目标元素才会出现在浏览器窗口内。

参考代码如下:


if (window.pageYoffset &gt; el.offsetTop - window.innerHeight &amp;&amp; window.pageYoffset &lt; el.offsetTop - el.offsetHeight) {}

当然,上面的是目标元素部分或整体出现在浏览器窗口的判断条件,如果是整个目标元素,方法同上,可参考下面的代码:


if (window.pageYoffset &gt; el.offsetTop - window.innerHeight - el.offsetHeight &amp;&amp; window.pageYoffset &lt; el.offsetTop) {}

虽然这种方法也可以,但它的浏览器兼容性不如第一种。

参考资料

原文地址:https://segmentfault.com/a/1190000017303509

判断DOM元素是否出现再浏览器窗口中的更多相关文章

  1. 利用闭包判断Dom元素和滚动条的方向

    本文收集整理自网上. 一,判断滚动条的方向,利用闭包首先保存滚动条的位置,然后当滚动时候不断更新滚动初始值,然后通过差指判断方向 function scroll(fn) { //利用闭包判断滚动条滚动 ...

  2. CSS中可以通过哪些属性定义,使得一个DOM元素不显示在浏览器可视范围内?

    最基本的: 设置display属性为none,或者设置visibility属性为hidden 技巧性: 设置宽高为0,设置透明度为0,设置z-index位置在-1000

  3. 一个窗口里包含一个iframe,点击iframe内的submit按钮,返回的视图总是显示在iframe中,我想要的效果是点击按钮后返回的视图是在浏览器窗口中...?asp.net mvc 的action中,不用js怎么实现??????????

    Content("<script type='text/javascript'>parent.location.href = '" + url + "';&l ...

  4. Phaser游戏框架与HTML Dom元素之间的通信交互

    本想按照PHASER的HTML Dom元素官方实例:http://labs.phaser.io/index.html?dir=game%20objects/dom%20element/&q=  ...

  5. JS判断指定dom元素是否在屏幕内的方法实例

    前言 刷网页的时候,有时会遇到这样一个情景,当某个dom元素滚到可见区域时,或者图片的懒加载效果,它就会展现显示动画,十分有趣.那么这是如何实现的呢? 实现原理 想要实现这个功能,就要知道具体的实现原 ...

  6. 部分浏览器上a标签包裹的dom元素显示不正常

    在苹果和部分安卓机上出现,pc端和chrome浏览器响应式设计里怎么样也不会出现的访问后a标签包裹的dom元素显示不正常a标签内的hr元素颜色显示不正常hr水平线的颜色被 bootstrap的css的 ...

  7. 浏览器中开发人员工具快速找到dom元素绑定那些JS事件

    在web开发过程中难免会遇到让程序员去修改一些js代码东西,例如js的ajax和php等语言的交互等,在这其中你不得不了解点js的事件触发,且随着js的盛行各种插件的事件让程序员眼花缭乱,所以借助一个 ...

  8. jQuery -&gt; 怎样【先创建、再改动、后加入】 DOM元素

    怎样一气呵成地.on the fly地操作DOM元素呢? 比如顺序运行[创建]-> [改动]-> [加入]三个动作. 因为jQuery支持链式操作,事实上就是设计模式的builder模式, ...

  9. DOM元素的位置、尺寸及更多的信息

    一.基本概念 document.documentElement是整个DOM树的根节点,对应的元素就是html.下面将其称作根元素或根节点. document.body,对应的元素是body 二.浏览器 ...

随机推荐

  1. cmake使用(CMakeList.txt)

    set(CMAKE_INCLUDE_CURRENT_DIR ON)#CMAKE_INCLUDE_CURRENT_DIR equal to INCLUDE_DIRECTORY(${CMAKE_CURRE ...

  2. luogu P1040 加分二叉树

    题目描述 设一个n个节点的二叉树tree的中序遍历为(1,2,3,-,n),其中数字1,2,3,-,n为节点编号.每个节点都有一个分数(均为正整数),记第i个节点的分数为di,tree及它的每个子树都 ...

  3. BEGINNING SHAREPOINT&#174; 2013 DEVELOPMENT 第12章节--SP 2013中远程Event Receivers 远程Event Receivers App级别生命周期

    BEGINNING SHAREPOINT® 2013 DEVELOPMENT 第12章节--SP 2013中远程Event Receivers  远程Event Receivers App级别生命周期 ...

  4. 我对Lamport Logical Clock的理解

    建议先看论文原文再来看这篇文章,我不会对论文中的各个点都具体说明.仅仅是写一些我自己的想法,帮助理解. 大家都知道.分布式环境下.确定各个事件发生的顺序非常重要,不然就会发生一些麻烦的问题. 考虑一下 ...

  5. Pro Android学习笔记(一三七):Home Screen Widgets(3):配置Activity

    文章转载仅仅能用于非商业性质,且不能带有虚拟货币.积分.注冊等附加条件.转载须注明出处http://blog.csdn.net/flowingflying/以及作者@恺风Wei. 通过widget定义 ...

  6. MySQL命令学习(一)

    今天我们来学习一下MySQL中的经常使用命令(MySQL中的命令keyword是不区分大写和小写的): (1)show databases; 显示MySQL中的全部database (2)create ...

  7. Libx264 编码错误 Input picture width(320) is greater than stride (0)

    Ffmpeg libx264编码出现 Input picture width(320) is greater than stride (0),问题出在视频格式不正确. libx264 编码要求输入源的 ...

  8. GB28181对接视频流

    今天抽空写下以GB28181的方式获取摄像机视频流以备后用,同时也希望能帮助到正着手开发GB28181对接视频的同学,这块的资料实在不多. 今天讲的内容不涉及到平台对接,平台对接下次有时间再讲,平台对 ...

  9. ORACLE 11G 单实例 磁盘文件系统 DG 归档日志删除脚本 基于RED HAT LINUX 5.3 X86 64BIT

    近期做个DG的归档日志删除, [oracle@.local logs]crontab -l * 8 * * * sh /home/oracle/dbscripts/del_arc.sh 该脚本分别调用 ...

  10. 深入Garbage First垃圾收集器(一)术语

    Garbage垃圾收集器的原理,在这篇博客中有讲到,可以拿来参考下, Getting Started with the G1 Garbage Collector(译) 另外在这篇博客中也有讲到很多垃圾 ...