标签: intersection-observer

Intersection Observer:每个元素只调用一次函数

我正在使用Intersection Observer API来跟踪网页上多个元素的可见性。当一个元素变得可见时,callback()应该执行一个函数。限制:对于每个元素,该函数只能执行一次。

这是我当前的网络分析项目实现:

const elements = document.querySelectorAll('[data-observable]');
const callback = str => { console.log(str); };
const observer = new IntersectionObserver(handleIntersection);

elements.forEach(obs => {
  observer.observe(obs);
});

function handleIntersection(entries, observer){
  entries.forEach(entry => {
    if (entry.intersectionRatio > 0) {
      // Call this function only once per element, without modifying entry object
      callback('observer-' + entry.target.getAttribute('data-observable'));
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

我正在努力寻找不修改现有元素 IntersectionObserver 或 IntersectionObserverEntries 的解决方案。

通常我会使用闭包来确保一个函数只执行一次:

function once(func) {
  let executed = false;
  return function() {
    if (!executed) {
      executed = …
Run Code Online (Sandbox Code Playgroud)

javascript intersection-observer

9
推荐指数
1
解决办法
6308
查看次数

多个 HTML 元素的相同交叉观察者

我正在尝试使某些文本项目停止与深色背景重叠,当用户滚动时,它们将逐一改变颜色。所有的文本项都是position: fixed

编辑:MDN 文档说(强调我的):

Intersection Observer API 提供了一种异步观察目标元素与祖先 元素交集变化的方法

我认为这意味着没有办法解决我的问题,因为我要监视重叠的元素不是root我在选项对象中指定的元素的子元素。

如果重叠元素不是另一个元素的子元素,有没有办法检测重叠?

if ('IntersectionObserver' in window) {

    const options = {
        root: document.getElementById('flow-landing'),
        rootMargin: '0px',
        threshold: 0
      }


    var callback = function(entries, observer) { 
            entries.forEach(entry => {

                if (entry.isIntersecting) {
                    entry.target.style.color = "white";
                }
                else {
                    entry.target.style.color = null;
                }
            });
          };

    const observer = new IntersectionObserver(callback, options);

    var targets = [Array.from(document.querySelectorAll('.social-item')), Array.from(document.querySelectorAll('.additional-item'))].flat();

    targets.forEach(target => 
        observer.observe(target));
}
Run Code Online (Sandbox Code Playgroud)

没有任何控制台错误,但代码没有做任何事情。

javascript intersection-observer

9
推荐指数
3
解决办法
1万
查看次数

确定元素覆盖了多少视口(IntersectionObserver)

我正在使用在IntersectionObserver元素进入视口时添加和删除元素的类。

我不想说“当元素的 X% 可见时 - 添加此类”,而是说“当元素的 X% 可见时当视口的 X% 被元素覆盖时 - 添加此类”。

我认为这是不可能的?如果是这样,我认为这有点缺陷,IntersectionObserver因为如果你有一个比视口高 10 倍的元素,它永远不会被视为可见,除非你将阈值设置为 10% 或更低。当您有可变高度元素时,尤其是在响应式设计中,您必须将阈值设置为 0.1% 之类的值才能“确定”该元素将接收该类(但您永远无法真正确定)。

编辑:回应摩西的答复。

Edit2:更新了几个阈值以强制它更频繁地计算percentOfViewport。还是不理想。

var observer = new IntersectionObserver(function (entries) {
	entries.forEach(function (entry) {
		var entryBCR = entry.target.getBoundingClientRect();
		var percentOfViewport = ((entryBCR.width * entryBCR.height) * entry.intersectionRatio) / ((window.innerWidth * window.innerHeight) / 100);

		console.log(entry.target.id + ' covers ' + percentOfViewport + '% of the viewport and is ' + (entry.intersectionRatio * 100) + '% visible');

		if (entry.intersectionRatio > …
Run Code Online (Sandbox Code Playgroud)

javascript intersection-observer

9
推荐指数
1
解决办法
7616
查看次数

交叉口观察者不能使用位置:固定的目标

我试图通过交集观察者调用回调.

我想要的targetstyle: "position: fixed",并通过移动它 style.top.

我还指定了根元素,它是目标的祖先style: "position: relative".

但是当目标和观察者相交时,不会触发回调函数.

我错过了一些限制吗?

这是我输入的内容:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>IO</title>
</head>
<body>
<div style="height: 200px;width: 100%;background: violet" class="upper">aaa</div>
<div style="position:relative;height: 200px;width: 100%;background: blueviolet" id="middle">bbb
    <div id="target" style="position:fixed;top: 0px;width: 50px;height: 50px;background: firebrick">ccc</div>
</div>
<script>
    let options = {
        root: document.getElementById("middle"),
        rootMargin: '0px',
        threshold: 0
    };
    let observer = new IntersectionObserver(entry => {
        console.log("observer's acting.")
    }, options);

    let target = document.getElementById("target");
    observer.observe(target);

    let stepping = 0; …
Run Code Online (Sandbox Code Playgroud)

javascript intersection-observer

8
推荐指数
1
解决办法
1446
查看次数

当元素已经在视口中时触发 IntersectionObserver

IntersectionObserver被触发时的元件是在视口中一定量(0-100%)可见。这意味着,当元素在视口中已经 100% 时,它不再触发,因为阈值没有变化。

我有一个高度为 的元素,当我滚动该元素时200vh,我希望IntersectionObserver触发。所以元素总是 100% 在视口内。

有没有办法在滚动元素时触发观察者?

我不能使用滚动事件,因为我使用的是 CSS scroll-snap,这会导致浏览器吞下事件,然后 JS 才能检测到它。

javascript intersection-observer

8
推荐指数
1
解决办法
918
查看次数

元素离开视口时的交集观察者

有没有一种方法可以使用“相交观察器”来检测元素是否离开视口?例如,我在屏幕上有一个元素,当元素的顶部碰到视口的顶部时,我想触发一个回调。从MDN:

Intersection Observer API使代码可以注册一个回调函数,该回调函数将在他们希望监视的元素进入或退出另一个元素(或视口)时,或者当两个相交的量改变请求的量时执行。-(https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API

因此,如果我做下面的事情,我会以为元素的顶部也到达视口的顶部时会触发回调?

var options = {
    root: document.querySelector('#element'),
    rootMargin: '0px',
    threshold: 0
}

var observer = new IntersectionObserver(callback, options);
Run Code Online (Sandbox Code Playgroud)

但是,只有当元素的顶部滚动并击中视口的底部时,才会触发该事件,但不能同时触发两者。有想法吗?

javascript intersection-observer

7
推荐指数
3
解决办法
1659
查看次数

当用户快速滚动并且 ref 对象停留在视图上时,Intersection Observer 问题

仅当用户快速滚动条形图或强制滚动条停留在按钮上时,Intersection Observer 才会出现问题。

不幸的是,新数据到达了,但由于用户按住滚动条,ref 对象保留在视图上。

如果用户快速滚动或按住滚动条,则会发生此问题。虽然接收到新数据需要下推加载框,但用户手动保持。所以观察者不会检测到变化。

用户需要再次上下滚动才能再次加载。

无论如何,要向组件添加计时器,以查看 2 秒后加载框是否仍在视图中并调用端点?换句话说,我如何获得 IntersectionObserver 的当前状态。查看它当前是否可见?

intersection intersection-observer

7
推荐指数
0
解决办法
473
查看次数

暗模式陷入路口

我一直在一个网站上工作,因此决定向其添加暗模式功能,我使用darkmode.js库实现了该库,该库基于原理工作mix-blend-mode: difference。但是,当我使用IntersectionObserver向其中添加滚动动画并启用了暗模式时,应该显示的div变成白色,然后立即变成黑色。是的,看起来似乎很复杂,所以

这是我的代码

const targets = document.querySelectorAll('.animate');
const options = {
  threshold: 0.7
}

const lazyLoad = target => {
  const io = new IntersectionObserver((entries, observer) => {
    console.log(entries)
    entries.forEach(entry => {
      console.log('');

      if (entry.isIntersecting) {
        const img = entry.target;
        img.classList.add('fade');
        observer.disconnect();
      }
    }, options)
  }, options);

  io.observe(target)
};

targets.forEach(lazyLoad);
Run Code Online (Sandbox Code Playgroud)
.quotes-layout {
	margin-top: 50px;
	display: flex;
	justify-content: center;
	margin-left: 10%;
	margin-right: 10%;
}

.quote {
	flex: 1;
	margin-right: 20px;
	text-align: left;
	background: #eee;
	padding: 20px 20px;
}

.quote …
Run Code Online (Sandbox Code Playgroud)

javascript css difference mix-blend-mode intersection-observer

7
推荐指数
0
解决办法
175
查看次数

crossObserver 只触发一次

我正在尝试使用新的 Intersection Observer API,但我只能触发一次它的事件。我相信我使用它是正确的,因为我几乎是逐字逐句地使用MDN 示例

https://jsfiddle.net/bukzor/epuwztn0/106/

function startObserver() {
  // Almost verbatim from MDN docs:
  //   https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
  let options = {
    root: document.querySelector('#svg'),
    rootMargin: '0px',
    threshold: 0.50,
  }

  let observer = new IntersectionObserver(onIntersection, options);

  let target = document.querySelector('circle');
  observer.observe(target);
}

function onIntersection(entries, observer) {
  // Simply log all intersectiono entries.
  console.log(observer)
  console.log("intersections:")
  entries.forEach(function(entry) {
    console.log(entry)
    // This code is just a wild guess, but it still won't fire a second time.
    observer.observe(entry.target)
  })
}
Run Code Online (Sandbox Code Playgroud)

当我运行它时,我在控制台中只有一个条目,而没有其他条目。它提到的零大小矩形,isVisible: false似乎是其他症状,但我一直无法找到原因。 …

javascript dom intersection-observer

7
推荐指数
0
解决办法
2377
查看次数

IntersectionObserver 不适用于长段 JS 的小屏幕

此脚本为活动部分发出活动类。最近注意到它在小屏幕上停止工作。即使在 chrome 的开发人员控制台中,我也会开始增加屏幕尺寸并且它会出现,一旦我开始缩小它就会立即停止工作(活动类消失)。但仅对于一个长部分,在较短的部分中一切正常。如何解决这个问题?

在代码片段中,我设置了一个较大的固定高度,因此投资组合链接不会接收活动类,在我的示例中,当部分宽度增加时,其高度会减小,因此在某些时候一切都会开始工作。

const links = document.querySelectorAll('.nav-link');
const sections = [... document.querySelectorAll('.forJS')];

const callback = (entries) => {
  links.forEach((link) => link.classList.remove('active'));
  const elem = entries.find((entry) => entry.isIntersecting);
  if (elem) {
    const index = sections.findIndex((section) => section === elem.target);
    links[index].classList.add('active');
  }
}

let observer = new IntersectionObserver(callback, {
  rootMargin: '0px',
  threshold: 0.5
});

sections.forEach((section) => observer.observe(section));
Run Code Online (Sandbox Code Playgroud)
section {
  height: 100vh;
  scroll-y: auto;
}
.long{
height: 300vh;
}
.nav-link.active{
  color: red;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet"/>
<body>
<header class="fixed-top">
  <nav …
Run Code Online (Sandbox Code Playgroud)

javascript ecmascript-6 intersection-observer

7
推荐指数
1
解决办法
363
查看次数