12

我正在尝试这样做,以便当某些文本项停止与深色背景重叠时,它们将在用户滚动时逐个更改颜色。所有的文本项都是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));
}

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

4

3 回答 3

11

稍微修改 Ruslan 的答案,因为在他的答案中,正在创建多个 Intersection Observer 对象。

通过调用多个元素,可以使用同一个观察者观察.observe()多个元素。

let observerOptions = {
    rootMargin: '0px',
    threshold: 0.5
}

var observer = new IntersectionObserver(observerCallback, observerOptions);

function observerCallback(entries, observer) {
    entries.forEach(entry => {
        if(entry.isIntersecting) {
          //do something
        }
    });
};

let target = '.targetSelector';
document.querySelectorAll(target).forEach((i) => {
    if (i) {
        observer.observe(i);
    }
});
于 2021-05-27T09:40:23.700 回答
4

你可以做这样的事情,至少它对我有帮助:

document.querySelectorAll('.social-item').forEach((i) => {
    if (i) {
        const observer = new IntersectionObserver((entries) => {
            observerCallback(entries, observer, i)
        },
        {threshold: 1});    
        observer.observe(i);
    }
})

const observerCallback = (entries, observer, header) => {
    entries.forEach((entry, i) => {
         if (entry.isIntersecting) {
             entry.target.style.color = "white";
         }
         else {
             entry.target.style.color = null;
         }
    });
};
于 2020-09-18T15:04:20.573 回答
-7

您可以使用offsetTopandoffsetHeight属性而不是IntersectionObserverAPI。

例如,当用户滚动时,您可以检查offsetTopofelement 2是否大于 theoffsetTop和小于offsetHeightof element 1

警告:使用 debounce 因为滚动事件的处理函数将为用户滚动的每个像素调用一次,想象一下如果用户滚动 600-1000 像素将会发生的性能噩梦。

LoDash文档它的去抖动功能描述为:

“[a function that] 创建一个 debounced 函数,该函数延迟调用func(处理程序)直到wait自上次调用 debounced 函数以来经过(时间)毫秒之后。”

如果你不使用 LoDash,这里有一个 Vanilla JavaScript debounce 函数:

function debounce(handler, time) {
  var timeout;
  return function() {
    var self = this, args = arguments;
    clearTimeout(timeout);
    timeout = setTimeout(function() {
      return handler.apply(self, args);
    }, time);
  };
}

如果“相交”,这是允许您“做事”的代码。element 2 element 1

let element_1 = document.querySelector("#my-element-1");
let element_2 = document.querySelector("#my-element-2");
window.addEventListener("scroll", debounce(() => {
  if(element_2.offsetTop > element_1.offsetTop && element_2.offsetTop < element_1.offsetHeight) {
    console.log("The elements are intersecting.");
  }
}, 100));

如果看起来很复杂或难以阅读,这里是相同的代码,分成更小的块:

let element_1 = document.querySelector("#my-element-1");

let element_2 = document.querySelector("#my-element-2");

window.addEventListener("scroll", debounce(() => {

  let x = element_2.offsetTop > element_1.offsetTop;

  let y = element_2.offsetTop < element_1.offsetHeight;

  if(x && y) {

    console.log("The elements are intersecting.");

  }

}, 250));

注释和信息:

  1. 您可以使用>=and<=运算符而不是>and<运算符
  2. 时间wait过长可能会使效果看起来不自然和强迫。

祝你好运。

于 2019-04-26T09:12:06.440 回答