javascript - 更改滚动到视口(viewport)时的事件状态

标签 javascript jquery html

我正在尝试制作一个静态网站,当 div 子元素进入视口(viewport)时(确切地说,当 div 元素进入视口(viewport)的上 50% 时),会将 side-nav 中相应的 div 类更改为“积极的”。它应该可以向下和向上滚动。

到目前为止,我已经尝试了其他线程的几种解决方案,但没有成功。我想我一直在错误地对待这个问题。

$(window).on('scroll', function() {
  $("#vars-args").each(function() {
  if (elementInViewport2($(this))) {
    $(this).find("#div1a").addClass("active");
  }
});
});

function elementInViewport2(el) {
  var top = el.offsetTop;
  var left = el.offsetLeft;
  var width = el.offsetWidth;
  var height = el.offsetHeight;

  while (el.offsetParent) {
    el = el.offsetParent;
    top += el.offsetTop;
    left += el.offsetLeft;
  }

  return (
    top < (window.pageYOffset + window.innerHeight) &&
    left < (window.pageXOffset + window.innerWidth) &&
    (top + height) > window.pageYOffset &&
    (left + width) > window.pageXOffset
  );
}
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
<div id="side-nav">
  <a href="" id="div1a">1</a>
  <a href="" id="div2a">2</a>
  <a href="" id="div3a">3</a>
  <a href="" id="div4a">4</a>
  <a href="" id="div5a">5</a>
  <a href="" id="div6a">6</a>
</div>
<div id="content">
  <div id="div1">
    <!--content-->
  </div>
  <div id="div2">
    <!--content-->
  </div>
  <div id="div3">
    <!--content-->
  </div>
  <div id="div4">
    <!--content-->
  </div>
  <div id="div5">
    <!--content-->
  </div>
  <div id="div6">
    <!--content-->
  </div>
</div>

另请注意,内部每个 div 的内容可以大于视口(viewport)的大小。

我在使用 javascript 时遇到了问题。另请注意,当前的 JS 是从其他线程复制的。

最佳答案

这可以使用 IntersectionObserver 来实现,正如@cloned 在评论中所说:https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API

要实现此目的,您需要一个作为参数传递的回调函数,该函数在isIntersectingtrue(一个选项)时执行 对象(下面将阈值设置为元素的 50%)和一个 IntersectionObserver

回调根据条目的 id 将事件类切换到 a 元素。

最后,我们循环遍历 div 并让观察者观察它们。

const callback = (entries, observer) => {
entries.forEach(entry => {
  const navItem = document.querySelector('#' + entry.target.id + 'a');
    if (entry.isIntersecting) {
      console.log(navItem.getAttribute('id'));
      navItem.classList.add('active');
    } else {
      navItem.classList.remove('active');
    }
  });
};
const options = {
  threshold: 0.5
};
const observer = new IntersectionObserver(callback, options);
const container = document.getElementById('content');
const targetElements = container.querySelectorAll('div');


targetElements.forEach(element => {
 observer.observe(element);
});

这里有一个JSBin来演示它 https://jsbin.com/riyuhediso/47/edit?html,js,console,output

请注意,虽然它证明了其可行性,但尚未针对可能很重要的性能问题进行分析,因此我不保证它。

如果您使用Bootstrap,您可以使用ScrollSpy lib https://getbootstrap.com/docs/4.1/components/scrollspy/还有很棒的 ScrollMagic http://scrollmagic.io/

关于javascript - 更改滚动到视口(viewport)时的事件状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53168030/

相关文章:

javascript - 当我将它添加到原始 html 时,html 属性 'readonly' 停止文本输入,但如果我通过 javascript 添加它则不会

html - 如何设置网格模板列容器的最小高度

html - html表格显示大量数据的设计思路

javascript - 如何获取特定表单FormData

javascript - 我可以用 Bootstrap 做一个部分吗?

jquery - 使用 SlideDown 显示 div

javascript - React 项目中的 Bootstrap 需要 jQuery

javascript - 爬虫中如何同步获取和保存

php - json_encode,json.parse 丢弃一个 '+' 字符?

javascript - 关闭在另一个事件函数中创建的模态