Intersection observer API提供了一种方法,可以异步观察目标元素与祖先元素或相对于浏览器视口(root)的交集变化。

很多种情况下都需要用到元素交集变化的信息,例如:当页面滚动时,懒加载图片或其他内容。

实现“可无限滚动”网站,也就是当用户滚动网页时直接加载更多内容,无需翻页。

为计算广告收益,检测其广告元素的曝光情况。

根据用户是否已滚动到相应区域来灵活开始执行任务或动画。

过去,交集检测通常需要涉及到事件监听,以及对每个目标元素执行Element.getBoundingClientRect()方法以获取所需信息。可是这些代码都在主线程上运行,所以任何一点都可能造成性能问题。

一睹为快:var options = {

root: document.querySelector('#scrollArea'),

rootMargin: '0px',

threshold: 1.0

}

var callback = function(entries, observer) {

entries.forEach(entry => {

//以下都是只读属性

entry.time; // 返回一个记录从 IntersectionObserver 的时间原点(time origin)到交叉被触发的时间的时间戳(DOMHighResTimeStamp).

entry.rootBounds; // 返回一个 DOMRectReadOnly 用来描述交叉区域观察者(intersection observer)中的根.

entry.boundingClientRect; // 返回包含目标元素的边界信息的DOMRectReadOnly. 边界的计算方式与 Element.getBoundingClientRect() 相同..

entry.intersectionRect; // 返回一个 DOMRectReadOnly 用来描述根和目标元素的相交区域.

entry.intersectionRatio; // 返回intersectionRect 与 boundingClientRect 的比例值.

entry.target; // 与根出现相交区域改变的元素 (Element).

});

};

//通过new IntersectionObserver()构造器创建并返回一个IntersectionObserver实例对象。

var observer = new IntersectionObserver(callback, options);

var target = document.querySelector('#listItem');

//为观察者对象添加一个观察元素

observer.observe(target);

callback

当元素可见比例超过指定阈值后,会调用一个回调函数,此回调函数接受两个参数:entries:一个IntersectionObserverEntry对象列表(list),每个被触发的阈值,都会较指定阈值有偏差(或超出或少于指定阈值)。

observer:被调用的IntersectionObserver实例对象。

options可选

一个可以用来配置observer实例的对象。如果options未指定,observer实例默认使用viewport作为根(root),并且没有margin, 阈值为0% (意味着即使1像素的改变都会触发回调函数)。你可以指定以下配置:root:监听元素的祖先元素Element对象,其边界盒将被视作viewport。目标在根的可见区域的的任何不可见部分都会被视为不可见。如果设置root参数为null或者不设置则root默认为设备视口)。

rootMargin:一个在计算交叉值时添加至根的边界盒(bounding_box)中的一组偏移量,类型为字符串(string) ,可以有效的缩小或扩大根的判定范围从而满足计算需要。语法大致和CSS 中的margin属性等同:上、右、下、左。默认值是"0px 0px 0px 0px".

threshold:规定了一个监听目标与边界盒交叉区域的比例值,可以是一个具体的数值或是一组0.0到1.0之间的数组。若指定值为0.0,则意味着监听元素即使与根有1像素交叉,此元素也会被视为可见. 若指定值为1.0,则意味着整个元素都是可见的。阈值的默认值为0.0.

IntersectionObserver实例对象方法IntersectionObserver.disconnect:使IntersectionObserver对象停止监听工作。

IntersectionObserver.observe:使IntersectionObserver开始监听一个目标元素。

IntersectionObserver.takeRecords:为所有监听目标返回一个IntersectionObserverEntry对象数组并且停止监听这些目标。

IntersectionObserver.unobserve:使IntersectionObserver停止监听特定目标元素。

滚动到相应区域执行css动画

....

....

const addAnimation = function(){

const observerEle = function(){

//选取元素

const elements = document.querySelectorAll('.b-block');

const options = {};

let imageCount = elements.length;

const observer = new IntersectionObserver(onIntersection,options);

Array.prototype.slice.call(elements).forEach(target=>{

//给选取的元素添加监听目标

observer.observe(target);

});

function onIntersection(entries,observer){

//终止对所有目标的监听观察

if (imageCount === 0) {

observer.disconnect();

}

entries.forEach(entry=>{

//entry.intersectionRatio = 1在视口内,0为不在视口内

//也可以试一试entry.isIntersecting为true在视口内,为false为不在视口内

if (entry.intersectionRatio > 0) {

imageCount--;

//停止监听当前目标元素

observer.unobserve(entry.target);

//给目标元素添加css动画类名

entry.target.classList.add('transition');

}

});

}

};

if('IntersectionObserver' in window ) observerEle();

}();

浏览器兼容的图片懒加载var lazyLoad = function() {

var IeModule = function(){

var map_element = {},

element_obj = [],

download_count = 0,

last_offset = -1,

doc = document,

doc_body = doc.body,

doc_element = doc.documentElement,

lazy_load_tag = "img",

imagesrcname = 'a',

thissrolltop = 400;

function initElementMap(){

var el = doc.getElementsByTagName(lazy_load_tag);

for (var j = 0, len2 = el.length; j < len2; j++) {

if (typeof el[j] == "object" && el[j].getAttribute(imagesrcname)){

element_obj.push(el[j]);

}

}

for (var i = 0, len = element_obj.length; i < len; i++) {

var o_img = element_obj[i],

t_index = getAbsoluteTop(o_img);

if (map_element[t_index]){

map_element[t_index].push(i);

}else{

var t_array = [];

t_array[0] = i;

map_element[t_index] = t_array;

download_count++;

}

}

}

function initDownloadListen(){

if (!download_count) return;

var getscrolltop = doc_body.scrollTop;

if(getscrolltop == 0){

getscrolltop = doc.documentElement.scrollTop;

}

var visio_offset = getscrolltop + doc_element.clientHeight;

if (last_offset == visio_offset){

setTimeout(initDownloadListen,200);

return;

}

last_offset = visio_offset;

var visio_height = doc_element.clientHeight + thissrolltop,

img_show_height = visio_height + getscrolltop;

// var allurlnum = parseInt(imageurlarray.length);

// if(allurlnum <= 0)

// {

// allurlnum = 1;

// }

var j = 0;

for (var key in map_element) {

if (img_show_height > key){

var t_o = map_element[key],

img_vl = t_o.length;

for (var l = 0; l < img_vl; l++) {

element_obj[t_o[l]].src = element_obj[t_o[l]].getAttribute(imagesrcname);

element_obj[t_o[l]].removeAttribute(imagesrcname);

j++;

}

delete map_element[key];

download_count--;

}

}

setTimeout(initDownloadListen, 200);

}

function getAbsoluteTop(element) {

if (arguments.length != 1 || element == null){

return null;

}

var offsetTop = element.offsetTop,

current = element.offsetParent;

while(current !== null){

offsetTop += current.offsetTop;

current = current.offsetParent;

}

return offsetTop;

}

function init(){

initElementMap();

initDownloadListen();

}

init();

},

observerImg = function(){

// 获取所有标记为懒惰加载的图像。

var images = document.querySelectorAll('img[a]'),

config = {//如果图像在y轴内达到上下50px,则开始下载。

rootMargin: '50px 0px',

threshold: 0.01

},

imageCount = images.length,

observer = new IntersectionObserver(onIntersection, config);

Array.prototype.slice.call(images).forEach(function(target){

observer.observe(target);

});

function onIntersection(entries) {

//终止对所有目标的观察

if (imageCount === 0) {

observer.disconnect();

}

entries.forEach(function(entry){

//1在视口内,0为不在视口内

if (entry.intersectionRatio > 0) {

imageCount--;

//停止观察并载入图像

observer.unobserve(entry.target);

preloadImage(entry.target);

}

});

}

function fetchImage(url) {

return new Promise(function(resolve, reject){

var image = new Image();

image.src = url;

image.onload = resolve;

image.onerror = reject;

});

}

function preloadImage(image) {

//const src = image.dataset.src;

var src = image.getAttribute("a");

if(!src) return;

return fetchImage(src).then(function(){ applyImage(image, src); });

}

function applyImage(img, src) {

// Prevent this from being lazy loaded a second time.

// img.classList.add('js-lazy-image--handled');

img.src = src;

img.classList.add('fade-in');

img.removeAttribute("a");

}

};

//如果我们没有支持交叉路口观察员,立即加载图像

if('IntersectionObserver' in window ){

observerImg();

return;

}

IeModule();

}()

Html图片懒加载动画,Intersection Observer实现滚动到相应区域执行动画及图片懒加载...相关推荐

  1. 使用Intersection Observer API创建无限加载组件

    本文章翻译自:https://vueschool.io/articles/vuejs-tutorials/build-an-infinite-scroll-component-using-inters ...

  2. dll文件懒加载_一步步学习NHibernate(5)——多对一,一对多,懒加载(2)

    请注明转载地址:http://www.cnblogs.com/arhat 通过上一章的学习,我们建立了Student和Clazz之间的关联属性,并从Student(many)的一方查看了Clazz的信 ...

  3. html等待图片全部加载,imgLoad等待图片资源加载完成后执行函数(图片预加载)...

    修改自一个2013年写的js判断图片资源加载完成后再执行函数的代码: 当时的代码片断需要手动加入需要确定加载完的图片名称到数组,比较麻烦,修改为插件后,不需要手动添加文件名称,只需对需要确定加载完成的 ...

  4. 懒加载和预加载的区别_类的动态创建(ro,rw)amp; 懒加载类和非懒加载类底层加载的区别 amp; 类和分类的搭配分析...

    黑客技术点击右侧关注,了解黑客的世界! Java开发进阶点击右侧关注,掌握进阶之路! Python开发点击右侧关注,探讨技术话题!作者丨OSMin链接:https://juejin.im/post/5 ...

  5. vue懒加载对话框API封装技巧(项目必备技能,适用于各种需要懒加载动态展示的弹框组件)

    懒加载对话框的方式做到了在你调用弹框展示API的那一刻,才去加载对话框文件并最终显示弹框效果.它最大的意义在于减少了你初次进入页面时加载的文件资源请求量和大小(加载资源小了,网页加载速度自然就提升了) ...

  6. java懒加载的原理_每天使用 Spring 框架,那你知道 lazy-init 懒加载原理吗?

    普通的bean的初始化是在容器启动初始化阶段执行的,而被lazy-init修饰的bean 则是在从容器里第一次进行context.getBean("")时进行触发. Spring ...

  7. 【JS】1067- 一个神奇的交叉观察 API Intersection Observer

    前言 前端开发肯定离不开判断一个元素是否能被用户看见,然后再基于此进行一些交互. 过去,要检测一个元素是否可见或者两个元素是否相交并不容易,很多解决办法不可靠或性能很差.然而,随着互联网的发展,这种需 ...

  8. HTML5和Intersection Observer的响应式图像优化简介

    by Riccardo Canella 里卡多·卡内拉(Riccardo Canella) HTML5和Intersection Observer的响应式图像优化简介 (An intro to res ...

  9. Qt图片定时滚动播放器+透明过渡动画

    目录 参考 结构 PicturePlay.pro main.cpp myqlabel.h 自定义QLabel myqlabel.cpp自定义QLabel pictureplay.h picturepl ...

最新文章

  1. cocos2d-x游戏开发(二)开始菜单续
  2. eclipse配置maven + 创建maven项目
  3. SAP Netweaver后台作业的几种状态
  4. Windows Azure Marketplace增加对六种语言和HTML5应用程序的支持
  5. Vmware中的centos虚拟机克隆之后没有eth0
  6. assembly 输出ab中所有数_.NET Core中批量注入Grpc服务
  7. corn java 可配置_定时任务工具——CronUtil
  8. 四种依恋类型_你们之间的爱情是哪种类型 | 爱情依恋关系测评
  9. bugzilla dbd-mysql_Ubuntu搭建bugzilla
  10. 《惢客创业日记》2019.03.04(周一)从创业角度看郭德纲(2)
  11. 实战教程:平面设计配色原则
  12. 浪潮存储加速国产替代
  13. LAMBDA表达式常用写法
  14. 国外2个在线web程序代码编辑网站
  15. 混频锁相环相关拓扑,性能以及错锁问题梳理
  16. 啥子是volatile
  17. 内核earlyprintk选项
  18. 设计模式-工厂模式三种类型
  19. 软件工程实验:数据库设计
  20. 卡西欧学生用计算机怎么玩,学生用卡西欧计算机用法(Students use CASIO computer).doc...

热门文章

  1. leetcode 1504. Count Submatrices With All Ones | 1504. 统计全 1 子矩形(单调栈)
  2. 【EasyUI】Tree中自定义在节点前是否显示checkbox
  3. C++ 静态线性表的顺序存储结构(数组实现)
  4. dart系列之:dart中的异步编程
  5. c4.5算法 程序语言,决策树之C4.5算法详解-Go语言中文社区
  6. android 蒙版图片带拖动_Android实现蒙版弹出框效果
  7. 未封装的扩展程序是什么意思_Android漏洞挖掘第三期:客户端完整性未校验
  8. LongCache机制与Long等值比较\\\\Integer 中的缓存类IntegerCache
  9. 干货:MySQL 索引原理及慢查询优化
  10. 缓存之EHCache