Выполнение анимации нескольких html-элементов

Я хочу анимировать разные разделы веб-страницы только тогда, когда они прокручиваются в поле зрения с помощью ванильного javascript. Вот как выглядит мой код прямо сейчас

<script>
    let target = document.querySelector("#who-we-are");
    let service = document.querySelector("#what-we-do");

    function animateAboutUs() {
        if (target.scrollIntoView) {
            document.querySelector("#who").classList.add("fadeIn");
        }
    }

    function animateServiceList() {
        if (service.scrollIntoView) {
            document.querySelector("#service").classList.add("fadeIn");
        }
    }

    window.onscroll = function() {
        animateAboutUs();
        animateServiceList();
    };
</script>

Проблема с этим заключается в том, что как только пользователь начинает прокручивать страницу вниз, раздел service анимируется, даже если он еще не виден.

Каков правильный способ сделать анимацию только тогда, когда раздел прокручивается для просмотра нескольких разделов?

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

Titus 22.05.2019 13:40

@Titus, так можно ли называть и animateAboutUs, и animateServiceList внутри window.scroll так, как я это делаю?

Mena 22.05.2019 13:44
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Введение в технологический стек Twitch
Введение в технологический стек Twitch
В этой статье мы подробно рассмотрим стек Twitch, который подразделяется на следующий набор технологий:
8 полезных HTML-тегов, которые лучше использовать вместо <div>
8 полезных HTML-тегов, которые лучше использовать вместо <div>
Когда я только начинал изучать html, я использовал div для всего, это был один из первых тегов, которые я выучил, и казалось, что он работает в любой...
HTML5: API локального хранилища (Local Storage)
HTML5: API локального хранилища (Local Storage)
LocalStorage - это простой способ хранения данных в браузере пользователя.
Доступность HTML - программирование с инклюзивной перспективой
Доступность HTML - программирование с инклюзивной перспективой
Представьте, что вы хотите поехать на пляж. Представьте, что вы упорно трудились весь год и заслужили это. Прибыв на место, вы обнаруживаете, что...
0
2
549
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

var $animation_elements = $('.animation-element');
var $window = $(window);
function check_if_in_view() {
var window_height = $window.height();
var window_top_position = $window.scrollTop();
var window_bottom_position = (window_top_position + window_height);

$.each($animation_elements, function() {
var $element = $(this);
var element_height = $element.outerHeight();
var element_top_position = $element.offset().top;
var element_bottom_position = (element_top_position + element_height );

//check to see if this current container is within viewport
if ((element_bottom_position >= window_top_position) &&
  (element_top_position <= window_bottom_position)) {
  $element.addClass('in-view');
} else {
  $element.removeClass('in-view');
  }
});
}
Ответ принят как подходящий

Современным решением было бы использовать Наблюдатель перекрестка вместо прослушивания события прокрутки.

Сначала вы определяете наблюдателя:

var options = {
  root: document.querySelector('#scrollArea'),
  rootMargin: '0px',
  threshold: 0.1
}
var observer = new IntersectionObserver(callback, options);

Порог .1 означает, что функция callback() вызывается, как только становится видимым 10% (или более). Отрегулируйте это, как вы считаете нужным, очевидно. Если вы опустите корневую опцию, будет использоваться область просмотра браузера.

Затем вы наблюдаете элементы:

var target = document.querySelector('.scrollItems');
observer.observe(target);

Теперь всякий раз, когда цель достигает порога, указанного для IntersectionObserver, вызывается обратный вызов.

var callback = function(entries, observer) { 
  entries.forEach(entry => {
    // this loops through each element that is visible, add your classes here
    entry.addClass('fadeIn');
  });
}

Примечание. Если вам также необходимо поддерживать старые браузеры, есть полифилл.

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

Mena 22.05.2019 14:11

IntersectionObserver такой классный, обожаю его. Спасибо, что познакомили меня с этим API.

Mena 22.05.2019 15:20

Рад, что смог помочь!

cloned 22.05.2019 16:24

Вот другое общее решение, использующее querySelectorAll, getBoundingClientRect и прослушиватели событий.

См. комментарии к примеру ниже:

document.querySelectorAll('.section').forEach(section => {
  const rect = section.getBoundingClientRect(); // get position of section
  if(rect.top < document.body.scrollTop + window.innerHeight){ // check initial if a section is in view
    section.classList.add('fadeIn');
  } else {
    window.addEventListener("scroll", addClass(section, rect)); // add eventlistener
  }
});

function addClass(element, rect) {
  const offset = 100; // set an offset to the needed scrollposition (in px)
  let handler = () => {
    if(rect.top < document.body.scrollTop + window.innerHeight - offset){ // check if scrollposition is reached
      element.classList.add('fadeIn');
      window.removeEventListener('scroll', handler); // remove eventlistener
      console.log(`reached section ${element.id}`);
    }
  };
  return handler;
}
.section {
  height: 100vh;
  color: transparent;
  text-align: center;
  font-size: 100px;
}

.section.fadeIn {
  color: #000 !important;
}

#one { background-color: yellow }
#two { background-color: green }
#three { background-color: orange }
#four { background-color: lightblue }
#five { background-color: grey }
<div class="section" id="one">Faded In!</div>
<div class="section" id="two">Faded In!</div>
<div class="section" id="three">Faded In!</div>
<div class="section" id="four">Faded In!</div>
<div class="section" id="five">Faded In!</div>

Другие вопросы по теме