为什么 Intersection Observer 在我的网站上不起作用?

Why does InteractionObserver not work on my website?

编辑: 此 post 已被编辑以标记对来自先前 InteractionObserver 实例的纯 JS InteractionObserver 实例的更新=40=] 使网站非常慢的装置。

新问题是,我设法让 Rickard 的想法在 Codepen 上工作,并进行了一些样式调整(在进入时将 .hidden 更改为 inverse .visible class),但为了我的生活,它在我的网站上不起作用。

具体来说,我认为这是没有切换的交叉点,我使用了 console.log 和提示来检查,它们根本没有启动,即使逐字复制代码也是如此。

旧代码,适用于上下文:

  // $(document).ready shorthand
  $("section, img, p, h1, h2, h3, h4, span").fadeIn("slow"); });

$(document).ready(function() {
  /* Every time the window is scrolled ... */
  $(window).scroll(function() {
    /* Check the location of each desired element */
    $("section, img, p, h1, h2, h3, h4, span").each(function(i) {
      var bottom_of_object = $(this).position().top + $(this).outerHeight();
      var bottom_of_window = $(window).scrollTop() + $(window).height();
      /* If the object is completely visible in the window, fade it in */
      if (bottom_of_window > bottom_of_object - 200) {
        $(this).animate({ opacity: "1" }, 1000),
        $(this).find('.lefttitle').animate({left:"0px"}, 1500);
        $(this).find('.righttitle').animate({right:"0px"}, 1500);
      }}); }); });

旧 CSS 标题

h2.lefttitle {float:left; text-align:left; left:10px; top:6px;}
h2.righttitle {float:right; text-align:right; right:10px; top:-6px;}

旧CSS动画

h3, section.projdescription * {animation:fadeInUp 2s both ease;}
*.visible {animation:fadeInUp 4s both ease;}
@keyframes fadeInUp {
  0% {opacity: 0;transform: translate3d(0,10px,0);}
  100% {opacity: 1;} }

您在滚动的每个像素中循环遍历大量元素,然后为 leftright 属性设置动画,这会强制重新计算所有对象并重新绘制。我会说浏览器会跳过动画,因为发生的事情太多了。

  1. 不要在滚动时设置动画。使用 IntersectionObserver.
  2. 不要使用 leftrighttopbottom 制作动画。使用 transform: translate 制作动画(就像您的动画一样),这不会强制重新计算其他元素的位置。一个热修复是使用 transform3d 激活硬件中的 3d 渲染。
  3. 您不需要使用关键帧来制作动画。只需使用 transition,并向元素添加一个相关的 class,当 intersectionObserver 触发时,它会改变它的位置或不透明度。

IntersectionObserver 一开始可能很难理解。您在每个要触发观察者 (see 1) 的 (section) 元素上放置一个观察者。将它们视为添加到数组 (entries)。然后观察者触发并将数组作为参数提供给您,您需要循环遍历它们中的每一个以查看它们是否相交 (see 2).

很抱歉没有在 JQuery 中写这个,但我对此感到生疏,因为今天 JQuery 并不是真正必要的。

// 2
let observer = new IntersectionObserver((entries) => {
  let section;

  // The same as writing ...
  // entries.forEach(function(entry) {

  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      section = entry.target;
      section.classList.remove('hidden');
    }
  })
});

  // 1
document.querySelectorAll('section').forEach((section) => {
  observer.observe(section);
});
section {
  color: white;
  font-size: 20px;
  padding: 1rem;
  min-height: 100vh;
  transition: opacity 5s;
}

section.hidden {
  opacity: 0;
}

section > .text {
  transition: transform 4s;
}

section.hidden > .text {
  transform: translateX(-2rem);
}

.blue {
  background-color: blue;
}

.red {
  background-color: red;
}

.black {
  background-color: black;
}
<section class="hidden blue">
  <div class="text">Something</div>
</section>

<section class="hidden red">
  <div class="text">Something, something</div>
</section>

<section class="hidden black">
  <div class="text">Last one, now!</div>
</section>

终于成功了!

这是实现奇迹的 JS 代码:

/* Margins for the Intersection */
const observerOptions = {
     root: null,
     threshold: 0,
     rootMargin: '0px 0px -100px 0px'
};

/* Add .visible Class to Intersection */
const observer = new IntersectionObserver(entries => {
     entries.forEach(entry => {
         if (entry.isIntersecting) {
           entry.target.classList.add('visible');
           observer.unobserve(entry.target);
         }
     });
}, observerOptions);

/* Listener for every element on the page */
window.addEventListener('DOMContentLoaded', (event) => {
  const sections = Array.from(document.querySelectorAll("*"));
  for (let section of sections) {
    observer.observe(section);
  }
});

现在这里有一些 CSS 动画:

/* Set the Initial State */
section, img, h1, etc {
  transition: padding-top 1s ease, opacity 1.5s ease;
  opacity: 0;
  padding-top: 20px;}
/* Act on Adding Visible State */
section.visible, img.visible, h1.visible, etc {
  opacity: 1;
  padding-top: 0px;}
/* Micromanage the Transitions */
img.visible {transition-duration: 0.5s}
h1.visible {transition-duration: 0.5s;}

现在继续改进它。我可能会将 JS querySelector 上的“*”更改为更简洁的选择(部分、img 等),但就目前而言,它会产生奇迹!