Благодаря этой жемчужине API большая часть работы выполняется за вас, когда вы пытаетесь вычислить положение вашего элемента при прокрутке страницы, что позволяет вам запечатлеть этот момент и выбрать анимацию по мере необходимости.

HTML

Давайте начнем с определения наших трех разделов нашего веб-сайта, как вы это обычно делаете. Вот мой пример:

<section class="section" id="about">
  <h1>About</h1>
</section>
<section class="section" id="portfolio">
  <h1>Portfolio</h1>
</section>
<section class="section" id="experience">
  <h1>Experience</h1>
</section>

Вы можете представить это как создание трех элементов, которые представляют собой три разных раздела моего веб-сайта.

Javascript

Теперь мы подошли к самой веселой части. Вы можете создать Обозреватель перекрестка следующим образом:

const observer = new IntersectionObserver(callback, options);

Как видите, он принимает два параметра, функцию обратного вызова и некоторые опции. Вы можете думать о них так: опции сообщают наблюдателю, на что вы хотите обратить внимание, и если то, что он находит, соответствует вашим критериям, то он вызывает вашу функцию обратного вызова.

Вот параметры для нашего примера:

const options = {
  threshold: [0.4, 0.8] // 0.4 = 40%, 0.8 = 80%
}

По сути, я говорю наблюдателю: «Эй, всякий раз, когда вы видите 40 % полного элемента или 80 % полного элемента, дайте мне знать». Это моменты, когда элемент Пересекается.

Что касается нашей функции обратного вызова:

const callback = (entries) => {
  entries && entries.forEach(entry => {
    if (entry.isIntersecting) {
      this.addClassName('visible');
    } else {
      this.removeClassName('visible');
    }
  });
};

Существует список «записей», которые должны быть получены нашей функцией обратного вызова от IntersectionObserver. Каждая «запись» представляет собой момент, когда элемент (или «цель», как мы можем их назвать) сообщил об изменении статуса своего пересечения.

Это означает, что наша функция обратного вызова сообщит нам, когда наш элемент «пересекается», а также когда он перестает пересекаться. Мы можем запечатлеть эти моменты, проверив свойство isIntersecting.

Наконец, мы можем собрать все это вместе следующим образом:

const options = {
  threshold: [0.4, 0.8] // 0.4 = 40%, 0.8 = 80%
}
const callback = (entries) => {
  entries && entries.forEach(entry => {
    if (entry.isIntersecting) {
      this.addClassName('visible');
    } else {
      this.removeClassName('visible');
    }
  });
};
const observer = new IntersectionObserver(callback, options);
const target = document.querySelector('#about'); // grab your element however you please
observer.observe(target); // start observing our element!

CSS

Что ж, самое сложное сделано, но, как вы видите, я показал функцию под названием addClassName в приведенном выше фрагменте кода. Эта функция — просто какой-то псевдокод, который я добавил, который добавит класс видимый и удалит его, когда элемент больше не будет отображаться на экране. В зависимости от того, как вы это разрабатываете, вы можете добавить имя класса через старый добрый элемент classlist или renderer2 Angular, если вы похожи на меня.

Независимо от того, как тогда выглядит CSS?

.section {
  opacity: 0;
  transition: opacity 1s ease-out;
  will-change: opacity;
}
.section.visible {
  opacity: 1;
}

Это добавляет забавное небольшое исчезновение, когда элемент появляется в поле зрения. По умолчанию ни один из элементов не будет виден.

Конечный результат

Вы можете найти полный код здесь с примером здесь: https://stackblitz.com/edit/angular-ivy-zgpxom?file=src/app/app.component.scss

Кстати, как я могу это сделать без Intersection Observer?

Старый способ хорошо, кучу Javascript, который вы бы написали сами. Удачи в попытках разобраться с оператором возврата функции, если вы еще не пили кофе.

//EVENT LISTENER
document.addEventListener('scroll', function(e) {
  const windowHeight = window.innerHeight;
  const elementVisible = 20; // 20px essentially
  const isAboutPage = this.isPage(windowHeight, elementVisible, 'about'); // have we reached element with id #about
  if (isAboutPage) {
    //do stuff here since we are on the page now
  }
}
//FUNCTION
isPage(windowHeight: any, elementVisible:any, elementID:string) {
  const workElement = document.getElementById(elementID);
  const elementTop = workElement?.getBoundingClientRect().top;
  return elementTop && (elementTop < windowHeight - elementVisible);
}

Подводя итог: здесь мы вручную находим верх нашего элемента и проверяем, видны ли его верхние 20 пикселей в текущем окне просмотра.

Заключение

Вот и все! Надеюсь, вам понравилось, пожалуйста, не стесняйтесь добавлять свои вопросы в комментарии ниже, так как их отзывы помогают мне писать лучше!