更改视图中淡入的偏移 javascript

Change the offset of a fade in when in-view javascript

我在一个网站的 js 中有一个淡入功能,当元素在垂直视口中时被激活。问题是,元素必须完全位于视口中才能激活该功能,而且我还设置元素在淡入时向上移动,你必须滚动很多才能让它工作,这有时会产生很多看起来不太好的空白。这是 js:

(function() {

  'use strict';

  // define variables
  var items = document.querySelectorAll(".fadeup");

  // check if an element is in viewport
  function isElementInViewport(el) {
    var rect = el.getBoundingClientRect();
    return (
      rect.top >= 0 &&
      rect.bottom <= (window.innerHeight || document.documentElement.clientHeight -50)
    );
  }


    function callbackFunc() {
      for (var i = 0; i < items.length; i++) {
        if (isElementInViewport(items[i])) {
          items[i].classList.add("in-view");
        }
      }
    }

    // listen for events
    window.addEventListener("load", callbackFunc);
    window.addEventListener("resize", callbackFunc);
    window.addEventListener("scroll", callbackFunc);

  })();

和css:

.fadeup {
  visibility: hidden;
  opacity: 0;
  position: relative;
  top: 30px;
  transition: opacity 1s, top 1s, visibility 1s;
  }

.fadeup.in-view {
  top: 0px;
  transform: none;
  visibility: visible;
  opacity: 1;
}

如何更改函数的偏移量,使其在元素完全位于视口中之前被激活?也许只是一半,或者一定数量的像素?我好像找不到路了

谢谢!

考虑做一个 IntersectionObserver。除了更有效地观察元素何时可见外,它还具有设置选项,可让您设置在触发之前元素的可见程度。

你的逻辑差不多了。您只需修改条件以检查 isElementInViewportrect 的底部,如下所示

// check if an element is in viewport
function isElementInViewport(el) {
    var rect = el.getBoundingClientRect();
    return (
      rect.top >= 0 &&
      //calculate from the top + a half of element
      rect.top + (rect.height/2) <= (window.innerHeight || document.documentElement.clientHeight)
    );
  }

完整测试代码

(function() {

  'use strict';

  // define variables
  var items = document.querySelectorAll(".fadeup");

  // check if an element is in viewport
  function isElementInViewport(el) {
    var rect = el.getBoundingClientRect();
    return (
      rect.top >= 0 &&
      rect.top + (rect.height/2) <= (window.innerHeight || document.documentElement.clientHeight)
    );
  }


    function callbackFunc() {
      for (var i = 0; i < items.length; i++) {
        if (isElementInViewport(items[i])) {
          items[i].classList.add("in-view");
        }
      }
    }

    // listen for events
    window.addEventListener("load", callbackFunc);
    window.addEventListener("resize", callbackFunc);
    window.addEventListener("scroll", callbackFunc);

  })();
.fadeup {
  visibility: hidden;
  opacity: 0;
  position: relative;
  top: 30px;
  transition: opacity 1s, top 1s, visibility 1s;
  height: 300px;
  border: 1px solid #ccc;
  }

.fadeup.in-view {
  top: 0px;
  transform: none;
  visibility: visible;
  opacity: 1;
}
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>

我们还可以使用另一种有效的方法来控制元素可见性 IntersectionObserver

这里有完整的例子

(function() {

  'use strict';

  var items = document.querySelectorAll(".fadeup");

  let observer = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        entry.target.classList.add("in-view");
      }

    });
  }, {
    threshold: 0.5 //whenever the element is visible on a half of the screen
  });
  items.forEach(p => {
    observer.observe(p)
  });

})();
.fadeup {
  visibility: hidden;
  opacity: 0;
  position: relative;
  top: 30px;
  transition: opacity 1s, top 1s, visibility 1s;
  height: 300px;
  border: 1px solid #ccc;
}

.fadeup.in-view {
  top: 0px;
  transform: none;
  visibility: visible;
  opacity: 1;
}
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>
<div class="fadeup">
  Content
</div>

但是我想记下一件事 IntersectionObserver 并不完全支持所有浏览器(您可以检查浏览器兼容性 here