根据window位置获取一个元素

Get an element based on window position

我想要完成的事情:当任何带有 class "yes" 的元素滚动到 window 中的特定 Y 位置时(我们假设它是window 的最顶部以保持简单),我只想获取该元素,以便我可以获取它的一些属性。

<div class="container">
  <div class="no"></div>
  <div class="yes"></div>
  <div class="yes"></div>
  <div class="yes"></div>
  <div class="yes"></div>
  <div class="no"></div>
</div>

我已经尝试了这两种方式,第一种方式 有效 ,但它似乎非常低效,因为它必须不断评估位置 all 滚动期间的元素。可能有很多。但也许我高估了它的效率有多低?

方法一:

$el = $('.yes');
$el.each(function(){
  var distance = $(this).offset().top;
  $window.scroll(function() {
    if ( $window.scrollTop() >= distance ) {
      // get the stuff
    }
  });
});

另一种方法似乎更有效(但也许不是?)但我还没有按需要使用它:

$window.scroll(function(){
    var el = document.elementsFromPoint(0, 0);
    var $el = $(el);
    if($el.hasClass('yes')){
        //get the stuff
    }
});

这似乎根本无法正常工作。拾取一些子元素“.yes”元素,即使这些元素本身没有 "yes" class,也根本无法拾取其他“.yes”元素。我不知道为什么。

(旁注:我已经简化了代码示例以消除其他效率,例如用于滚动的 setTimeout 和测试仅在我尝试获取的元素发生变化时才执行功能,等等......我只需要弄清楚了解如何让位置测试发挥最佳作用)。

我想你要找的是 intersection/observer API

<div class="container">
  <div class="no"></div>
  <div lang="javascript" class="yes"></div>
  <div class="no"></div>
  <div lang="python" class="yes"></div>
  <div class="no"></div>
  <div lang="go" class="yes"></div>
  <div class="no"></div>
  <div lang="rust" class="yes"></div>
  <div class="no"></div>
  <div class="end"><h1>HOORAY! YOU KNOW KNOW THE INTERSECTION OBSERVER API</h1>
    <a href="https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver" target="_new" rel="noopener">Read more about it here</a>
  </div>
</div>


<script>
let observer = new IntersectionObserver((divs, observer) => { 
    divs.forEach(div => {
        if(div.isIntersecting){
            //grab your attributes
            var _target = div.target
            let theAttr = _target.getAttribute("lang");
            console.log('div is intersecting with language attribute of: ' + theAttr);
            observer.unobserve(div.target);
        }
    });
    }, {threshold: 1});

document.querySelectorAll('div.container > div.yes').forEach(div => { observer.observe(div) });
 </script>
<style>
.container {height: 500vh;}
.no {background-color: #e87e7e;
height: 50vh;}
.yes {background-color: #00800478;
height: 50vh;}
.end{text-align: center;}
</style>

here is mozilla's documentation on the intersection/observer API.