做多个HTML元素动画

时间:2019-05-22 11:38:38

标签: javascript 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部分就会获得动画效果,即使该页面尚未显示。

仅当将部分滚动到多个部分的视图中时,制作动画的正确方法是什么?

3 个答案:

答案 0 :(得分:1)

一种现代的解决方案是使用Intersection Observer而不是监听滚动事件。

首先,您定义观察者:

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

.1的阈值表示callback()函数在可见10%(或更多)时立即被调用。调整为您认为合适的位置。 如果省略root选项,则使用浏览器视口。

然后您观察以下项目:

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');
  });
}

注意:如果您还需要支持较旧的浏览器,请there is a polyfill available.

答案 1 :(得分:0)

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');
  }
});
}

答案 2 :(得分:0)

这是使用querySelectorAllgetBoundingClientRecteventListeners的另一种通用解决方案。

请参阅以下示例的注释:

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>