IntersectionObserver:ES6新的监听器API,能够监听一个或者多个盒子和浏览器可视窗口的交叉信息,只要盒子和可视窗口的交叉信息发生变化,则监听器就会被触发,我们可以做一些自己想做的事情

一、API

IntersectionObserver是浏览器原生提供的构造函数,接受两个参数:callback是可见性变化时的回调函数,option是配置对象(该参数可选)。
构造函数的返回值是一个观察器实例。实例的observe方法可以指定观察哪个 DOM 节点

  1. //let ob = new IntersectionObserver(callback, option);
  2. let ob = new IntersectionObserver(callback,{
  3. //控制一露头算交叉状态改变0 默认为0 还是完全出现才算交叉状态改变1
  4. threshold:[1]
  5. //thresholds属性值为[0, 0.25, 0.5, 0.75, 1]
  6. })
  1. // 监听DOM元素
  2. ob.observe(document.querySelector('#box'));
  3. // 移除监听
  4. ob.unobserve(element);

上面代码中,observe的参数是一个 DOM 节点对象。如果要观察多个节点,就要多次调用这个方法。

  1. ob.observe(elementA);
  2. ob.observe(elementB);

二、callback 参数

目标元素的可见性变化时,就会调用观察器的回调函数callback<br />

  1. let ob = new IntersectionObserver(changes => {
  2. // 触发:
  3. // + 监听DOM元素后触发一次
  4. // + 刚一进入视口 触发一次
  5. // + 完全离开视口 触发一次
  6. console.log(changes);
  7. });

上面代码中,回调函数采用的是箭头函数的写法。callback函数的参数(changes)是一个数组,每个成员都是一个IntersectionObserverEntry对象。举例来说,如果同时有两个被观察的对象的可见性发生变化,changes数组就会有两个成员。

参数是个数组,即 changes=[…] ,数组中的每一项都是监听的元素的交叉信息,但可以循环绑定多次元素
示例:瀑布流案例中,一次只能监听一种元素(img),但img有多个,所以数组中每一项就是对应的交叉信息

  1. let ob=new IntersectionObserver(changes=>{
  2. // 循环每个盒子监听到的交叉盒子,把出现在视口中的盒子做延迟加载
  3. changes.forEach(change=>{
  4. let{isIntersecting,target}=change;
  5. // target监听的盒子
  6. //isIntersecting 为 true 则是显示在了视口中
  7. // console.log(change);
  8. if(isIntersecting){
  9. // 当前盒子已经出现在视口中 target监听的盒子
  10. singleImgLazy(target.querySelector('img'));
  11. // 处理后 ,这个盒子就没必要再监听了
  12. ob.unobserve(target);
  13. }
  14. });
  15. },{
  16. // 控制完全出现在视口中 才算交叉状态改变
  17. threshold:[1]
  18. });

三、IntersectionObserverEntry 对象

IntersectionObserverEntry对象提供目标元素的信息每个属性的含义如下。
image.png

  • target:监听的这个DOM元素对象
  • boundingClientRect:元素和可视窗口的交叉信息
  • isIntersecting:false 记录当前元素是否出现在可视窗口中(默认一露头就算)
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>IntersectionObserver</title>
  8. <link rel="stylesheet" href="css/reset.min.css">
  9. <style>
  10. html,
  11. body {
  12. height: 200%;
  13. background: -webkit-linear-gradient(top left, pink, orange);
  14. }
  15. #box {
  16. position: absolute;
  17. left: 200px;
  18. top: 800px;
  19. width: 100px;
  20. height: 100px;
  21. background: red;
  22. }
  23. </style>
  24. </head>
  25. <body>
  26. <div id="box"></div>
  27. <script>
  28. let box = document.querySelector('#box');
  29. /* let ob = new IntersectionObserver(changes => {
  30. // 当监听的元素和可视窗口交叉信息发生改变的时候触发执行
  31. // + changes记录每一个被监听的元素和可视窗口的交叉信息(数组)
  32. // 每一项记录的信息
  33. // boundingClientRect:{...} 元素和可视窗口的交叉信息
  34. // isIntersecting:false 记录当前元素是否出现在可视窗口中(默认一露头就算)
  35. // target:... 监听的这个DOM元素对象
  36. // 触发:
  37. // + 监听DOM元素后触发一次
  38. // + 刚一进入视口 触发一次
  39. // + 完全离开视口 触发一次
  40. console.log(changes);
  41. });
  42. // 监听DOM元素 unobserve就是移除监听
  43. ob.observe(box); */
  44. let ob = new IntersectionObserver(changes => {
  45. // 交叉状态改变,就会被触发执行
  46. console.log(changes);
  47. }, {
  48. // 控制一露头算交叉状态改变0 还是完全出现才算交叉状态改变1
  49. threshold: [1]
  50. });
  51. ob.observe(box);
  52. </script>
  53. </body>
  54. </html>