【问题标题】:How detect which child element is visible after scrolling the parent div?滚动父div后如何检测哪个子元素可见?
【发布时间】:2019-07-12 03:23:29
【问题描述】:

我想使用 div(如 PDF 阅读器)模拟“当前页面”之类的内容

document.addEventListener("DOMContentLoaded", function(event) {
  var container = document.getElementById("container");
  container.onscroll = function() {
    let position = container.scrollTop;
    let divs = document.querySelectorAll('.page');
    for (div of divs) {
      //???
    }
  }
});
#container {
  width: 400px;
  height: 600px;
  overflow: auto;
}

.page {
  width: 400px;
}

.red {
  background-color: red;
  height: 600px;
}

.blue {
  background-color: blue;
  height: 400px;
}
Current page: <span id="page-counter">1</span>
<div id='container'>
  <div id="div-1" class="page red"></div>
  <div id="div-2" class="page blue"></div>
  <div id="div-3" class="page red"></div>
  <div id="div-4" class="page blue"></div>
</div>

所以,我想知道最好的方法,例如,在第三个 div“出现”时将 span page-counter 文本更改为“3”

类似这样的:https://i.imgur.com/rXQ2Bw8.png

提前致谢 塞尔索

【问题讨论】:

  • 什么定义了 div 何时“出现”?当前一个完全不在屏幕上时?只要 div 完全可见?当它完全可见时?
  • 类似于原生 firefox pdf 阅读器:i.imgur.com/rXQ2Bw8.png

标签: javascript html css scroll


【解决方案1】:

由于此问题从未标记 jQuery,因此这是一个纯 Javascript 解决方案,据我所知,它可以模拟您正在寻找的行为。该解决方案计算容器内当前可见的每个子元素的像素数量。如果金额大于或等于容器大小的一半,则假定这是您的访问者正在查看的页面。

function getVisibleHeight(element){
	const container = document.getElementById("container");
	let scrollTop = container.scrollTop;
	let scrollBot = scrollTop + container.clientHeight;
	let containerRect = container.getBoundingClientRect();
	let eleRect = element.getBoundingClientRect();
	let rect = {};
	rect.top = eleRect.top - containerRect.top,
	rect.right = eleRect.right - containerRect.right,
	rect.bottom = eleRect.bottom - containerRect.bottom,
	rect.left = eleRect.left - containerRect.left;
	let eleTop = rect.top + scrollTop;
	let eleBot = eleTop + element.offsetHeight;
	let visibleTop = eleTop < scrollTop ? scrollTop : eleTop;
	let visibleBot = eleBot > scrollBot ? scrollBot : eleBot;

	return visibleBot - visibleTop;
}

document.addEventListener("DOMContentLoaded", function(event) {
	const container = document.getElementById("container");
	const divs = document.querySelectorAll('.page');

	container.addEventListener("scroll", () => {
		for(let i=0; i<divs.length; i++){
			const containerHeight = container.clientHeight;

			// Gets the amount of pixels currently visible within the container
			let visiblePageHeight = getVisibleHeight(divs[i]);

			// If the amount of visible pixels is bigger or equal to half the container size, set page
			if(visiblePageHeight >= containerHeight / 2){
				document.getElementById('page-counter').innerText = i+1;
			}
		}
	}, false);
});
#container {
	width: 400px;
	height: 300px;
	overflow: auto;
}

.page {
	width: 380px;
}

.red {
	background-color: red;
	height: 300px;
}

.blue {
	background-color: blue;
	height: 200px;
}
Current page: <span id="page-counter">1</span>
<div id='container'>
	<div id="div-1" class="page red"></div>
	<div id="div-2" class="page blue"></div>
	<div id="div-3" class="page red"></div>
	<div id="div-4" class="page blue"></div>
</div>

【讨论】:

    【解决方案2】:

    这里的一般方法是编写一个函数来确定给定的 HTML 元素是否在视口中。您可以在用户滚动时运行检查。有关 jQuery 的示例,请参见下面的 sn-p。我不一定说这是执行此操作的 最佳 方法,但它似乎正在工作。开始滚动以查看出现的 ID。

    function isInViewPort(element) {
      // Function will determine if any part of the element is in the viewport.
      let $el = $("#" + element);
      let windowScrollTop = $(window).scrollTop();
      let windowHeight = $(window).height();
      let windowBottom = windowScrollTop + windowHeight;
      let elementTop = $el.offset().top;
      let elementOuterHeight = $el.outerHeight();
      let elementBottom = elementTop + elementOuterHeight;
    
      let isAboveViewPort = elementBottom < windowScrollTop;
      let isBelowViewPort = windowBottom < elementTop;
    
      return !(isAboveViewPort || isBelowViewPort);
    }
    
    let currentDiv;
    
    $("#container").on("scroll", function() {
      $("#container").find("div").each(function() {
        if (isInViewPort(this.id) && currentDiv !== this.id) {
          $("#page").html("Current ID is " + this.id)
          currentDiv = this.id;
        }
      });
    });
    #container {
      overflow: auto;
      height: 300px;
    }
    
    .red {
      background-color: red;
      height: 600px;
    }
    
    .blue {
      background-color: blue;
      height: 400px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <span id="page"></span>
    <div id='container'>
      <div id="div-1" class="page red"></div>
      <div id="div-2" class="page blue"></div>
      <div id="div-3" class="page red"></div>
      <div id="div-4" class="page blue"></div>
    </div>

    【讨论】:

      【解决方案3】:

      您可以在 jQuery 中使用 is visible 功能。只需给每个 div 一个唯一的 ID 或类。

      if( $("#uniqueIdHere").is(':visible'))
         $(".page3Selector").addClass('active');
      

      然后要删除活动类,您可以将其与 else 语句配对以删除非活动 div 的类。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-03
        • 2022-09-22
        • 1970-01-01
        • 2012-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多