【问题标题】:Check if element is partially in viewport检查元素是否部分在视口中
【发布时间】:2015-09-05 18:18:04
【问题描述】:

我正在尝试确定一个元素在视口中是部分还是完全

我发现这将确定一个元素是否完全可见,但在尝试确定部分可见性时会一直感到困惑。我不想使用 jQuery。

基本上,这个想法是页面上会有一个元素可能不在视图中。一旦用户将该元素滚动到视图中,即使是部分滚动,它也应该触发一个事件。我将通过绑定一个 onscroll 事件来处理事件触发器。我只需要检测才能正常工作。

function isInViewport(element) {
    var rect = element.getBoundingClientRect();
    var html = document.documentElement;
    return (
        rect.top >= 0 &&
        rect.left >= 0 &&
        rect.bottom <= (window.innerHeight || html.clientHeight) &&
        rect.right <= (window.innerWidth || html.clientWidth)
    );
}

任何帮助将不胜感激!

【问题讨论】:

  • 不检查top &gt;= 0bottom &lt;= html.clientHeight,您可以翻转它们以获得部分可见性,即bottom &lt;= 0 &amp;&amp; top &gt;= html.clientHeight
  • 这是一个很棒的解决方案,可让您选择完全或部分可见性:github.com/libshin/inViewport/blob/master/index.js

标签: javascript


【解决方案1】:

迟到的答案,但大约一个月前,我写了一个函数,它可以确定一个元素在视口中的可见程度,以百分比衡量。我已经在 iphone/ipad 上的 chrome、firefox、ie11、ios 中对其进行了测试。当元素的 X 百分比(从 0 到 100 的数字)可见时,该函数返回 true。仅确定元素的测量值是否可见,而不确定元素是否被不透明度、可见性等隐藏。

const isElementXPercentInViewport = function(el, percentVisible) {
  let
    rect = el.getBoundingClientRect(),
    windowHeight = (window.innerHeight || document.documentElement.clientHeight);

  return !(
    Math.floor(100 - (((rect.top >= 0 ? 0 : rect.top) / +-rect.height) * 100)) < percentVisible ||
    Math.floor(100 - ((rect.bottom - windowHeight) / rect.height) * 100) < percentVisible
  )
};

【讨论】:

  • 很酷的功能,这为我节省了很多时间!
  • 这很酷。有人可以解释+-(rect.height / 1) 应该做什么吗?如果它应该是翻转高度的标志,那为什么不只是-rect.height
  • 你有一个好点,它似乎(很明显)是多余的,所以我在帖子中更新了我的答案。
  • 很棒的工作@folo
  • @folo 当我必须为没有开发团队的客户抓取这些产品并且我需要将其发送到 GA/GA4 时,这非常适合捕获产品印象
【解决方案2】:

您需要基于element.offsetTopelement.offsetLeftelement.offsetHeightelement.offsetWidthwindow.innerWidthwindow.innerHeight 的解决方案

(根据情况,您可能还需要考虑滚动位置)

function isInViewport(element){
  if(element.offsetTop<window.innerHeight && 
       element.offsetTop>-element.offsetHeight
     && element.offsetLeft>-element.offsetWidth
     && element.offsetLeft<window.innerWidth){
      return true;
    } else {
      
      return false;
    }
}



function test(){
  alert(isInViewport(document.getElementById("elem"))?"Yes":"No"); 
}
#elem{width: 20px; height: 20px; background: red; }
#elem{position: absolute;top: -9px;left: 600px;}
    <div id="elem"></div>
    <button onclick="test()">Check</button>

【讨论】:

  • 如何将滚动位置纳入其中?基本上,这个想法是页面上会有一个元素可能不在视野范围内。一旦用户将该元素滚动到视图中,即使是部分滚动,它也应该触发一个事件。我将通过绑定一个 onscroll 事件来处理事件触发器。我只需要检测才能正常工作。感谢您迄今为止的帮助!
  • 它说是,并且它的位置是-9px,这意味着不是完全可见
【解决方案3】:

function partInViewport(elem) {
    let x = elem.getBoundingClientRect().left;
    let y = elem.getBoundingClientRect().top;
    let ww = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
    let hw = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
    let w = elem.clientWidth;
    let h = elem.clientHeight;
    return (
        (y < hw &&
         y + h > 0) &&
        (x < ww &&
         x + w > 0)
    );
}

document.addEventListener("scroll", ()=>{
	let el = document.getElementById("test");
	if (partInViewport(el)) {
  	document.getElementById("container").style.backgroundColor = "green";
  } else {
  	document.getElementById("container").style.backgroundColor = "red";
  }
});
#test {
  height: 200px;
  width: 145px;
  background-color: grey;
}
#container {
  height: 400px;
  width: 345px;
  transform: translate(400px, 360px);
  background-color: red;
  display: grid;
  align-items: center;
  justify-items: center;
}
body {
  height: 1500px;
  width: 1500px;
}
<div id="container">
  <div id="test"></div>
</div>

我的代码示例: https://jsfiddle.net/xqpebwtv/27/

【讨论】:

  • 这不考虑父容器的可能偏移量。
【解决方案4】:

你的代码是这样说的:

  • 元素的顶部必须低于窗口的顶部,
  • 元素的左侧必须在窗口左侧的右侧,
  • 元素的底边必须位于窗口底边的顶部,并且
  • 元素的右侧必须在窗口右侧的左侧

你想要什么:

  • 元素的顶部必须低于窗口的顶部,或者元素的底部必须高于窗口的底部,并且
  • 元素的左侧必须位于窗口左侧的右侧,或者元素的右侧必须位于窗口右侧的左侧

随心所欲,这里的代码应该足够简单。

【讨论】:

    【解决方案5】:

    应该这样做,不需要偏移,因为我们正在比较客户矩形。

    function isPartiallyVisibleInViewport(element, viewport) {
      var bound = element.getBoundingClientRect();
      var bound2 = viewport.getBoundingClientRect();
      return bound.bottom > bound2.top && bound.top < bound2.bottom;
    }
    

    这个函数只做垂直检查,如果你还想水平检查,必须扩展:

    return bound.bottom > bound2.top && bound.top < bound2.bottom && bound.right > bound2.left && bound.left < bound2.right;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-12
      • 2014-01-14
      • 2021-06-03
      • 2022-08-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多