在达到 50% 视口高度时使用 IntersectionObserver 和 rootMargin 进行更改

Use IntersectionObserver with rootMargin to change when reaching 50% viewport height

路口观察者rootMargin property让我彻底懵了

我的目标是在元素的一半高度穿过视口的垂直中心时向该元素添加 class。

在我当前的项目中,我所做的任何事情似乎都不会影响 "root intersection rectangle",并且总是立即添加 class。我在最新的 Chrome 和 Firefox 中测试过。

这是简化的测试用例:

// https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API

const options = {
  root: null, // default, use viewport
  rootMargin: '0px 0px -50% 0px',
  threshold: 0.5 // half of item height
}

const circle = document.getElementById('circle');

const observerCallback = function(entries, observer) {
  console.log('intersected');
  circle.classList.add('intersected');
}

window.addEventListener('load', function(event) {

  const observer = new IntersectionObserver(observerCallback, options);

  observer.observe(circle);

}, false);
.circle {
  margin: 100vh auto;
  width: 200px;
  height: 200px;
  background-color: tomato;
  border-radius: 50%;
  transition: background-color 2s ease-in-out;
}

.circle.intersected {
  background-color: mediumseagreen;
}
<div class="circle" id="circle"></div>

我自己有时对 IntersectionObserver 很困惑,但参考 this post,它对我来说更容易掌握。

可能给您带来麻烦的是检查 if 它是否确实相交。所以我添加了一个 if-statement 以及在 IntersectionObserver 条目上找到的 属性 isIntersecting

我还添加了对 IntersectionObserver 的检查(如果它在客户端可用)并从选项中删除了 root: null,因为无论如何它都应该默认为视口。

如果您只使用此 IntersectionObserver 添加一次 class,请不要忘记在不再需要时添加 observer.unobserve(circle)observer.disconnect() 以防止内存泄漏。

// https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API

const options = {
  rootMargin: '0px 0px -50% 0px',
  threshold: 0.5 // half of item height
}

const circle = document.getElementById('circle');

const observer = new IntersectionObserver(entries => {
  const [{ isIntersecting }] = entries
  if (isIntersecting) {
    console.log('intersected');
    circle.classList.add('intersected');
  } else {
    console.log('not-intersecting');
  }
}, options);

window.addEventListener('load', () => {
  if ('IntersectionObserver' in window) observer.observe(circle);
}, false);
.circle {
  margin: 100vh auto;
  width: 200px;
  height: 200px;
  background-color: tomato;
  border-radius: 50%;
  transition: background-color 2s ease-in-out;
}

.circle.intersected {
  background-color: mediumseagreen;
}
<div class="circle" id="circle"></div>