在拥有滚动条元素内滚动时,判断其子元素是否出现(达到可视区域)公式

583 阅读2分钟

问题描述

网上的帖子大多数是:判断一个元素是否在可视区域中

而帖子中举的例子,也是以浏览器最外层body/html的滚动条为例子,进行讲解,基本上都是如下的效果图:

注意这里的滚动条是最外层的

111.gif

  • 实际上,我们页面的滚动条,有时,并不是以最外层的body或者html进行滚动的
  • 可能是页面中间的某一个dom元素可以滚动
  • 我们需要判断这个dom滚动元素内的某一个小dom目标元素何时出现,何时达到可视区域
  • 这里的可视区域是能看到,和最外层的那个滚动条没有关系的
  • 如下效果图

如需求:当红色盒子在内层滚动条滚动中出现时,就更改对应dom元素背景色为粉红色

222.gif

注意这里有两个滚动条,我们的需求是里面的滚动条滚动时,去做对应控制

公式提出

  • 其实也很简单,首先我们分析一些元素层级结构。
  • 最外层的肯定是bodyhtml,这个不用管它
  • body标签内部,有一个<div class="scrollBox"></div>,这个dom元素拥有滚动条
  • 而在.scrollBoxdom元素内,还有一个目标元素<div class="target"></div>,看看这个目标元素.target何时出现,何时达到可视区域

公式:

滚动距离出现 = .target距顶部高度 - .scrollBox距顶部高度 - .scrollBox自身高度

滚动距离出现 = .target距顶部高度 - .scrollBox距顶部高度 - .scrollBox自身高度

滚动距离出现 = .target距顶部高度 - .scrollBox距顶部高度 - .scrollBox自身高度

或:

边界值 = 目标元素距顶部高度 - 滚动盒子容器距顶部高度 - 滚动盒子容器自身高度

边界值 = 目标元素距顶部高度 - 滚动盒子容器距顶部高度 - 滚动盒子容器自身高度

边界值 = 目标元素距顶部高度 - 滚动盒子容器距顶部高度 - 滚动盒子容器自身高度

即,当滚动的距离超过这个边界值时,目标元素就会出现

这里的边界值,一定是初始边界值,就是要提前算好,最好存一份,因为滚动的话,会更改相应距离位置的

复制粘贴代码看效果更好理解:

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
		.scrollBox {
			width: 100%;
			height: 300px;
			background-color: #ccc;
			/* 拥有滚动条 */
			overflow-y: auto;
		}

		.target {
			width: 60px;
			height: 60px;
			background-color: red;
		}
	</style>
</head>

<body>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<div class="scrollBox">
		<h1>孙悟空</h1>
		<h1>孙悟空</h1>
		<h1>孙悟空</h1>
		<h1>孙悟空</h1>
		<h1>孙悟空</h1>
		<h1>孙悟空</h1>
		<h1>孙悟空</h1>
		<h1>孙悟空</h1>
		<h1>孙悟空</h1>
		<h1>孙悟空</h1>
		<div class="target"></div>
	</div>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<script>
		let scrollBoxDom = document.querySelector('.scrollBox')
		let targetDom = document.querySelector('.target')
		// 注意!这里的边界值,是原始的位置的值,因为滚动的话,会更改元素的getBoundingClientRect的相关值
		let boundaryValue = targetDom.getBoundingClientRect().top - scrollBoxDom.getBoundingClientRect().top - scrollBoxDom.offsetHeight
		// 边界值 = 目标元素距离顶部高度 - 滚动盒子容器距离顶部高度 - 滚动盒子容器自身的高度
		function callBack() {
			if (scrollBoxDom.scrollTop > boundaryValue) {
				console.log('在可视区域');
				scrollBoxDom.style.backgroundColor = 'pink'
			} else {
				console.log('不在可视区域');
				scrollBoxDom.style.backgroundColor = '#ccc'
			}
		}
		scrollBoxDom.addEventListener('scroll', callBack)
	</script>
</body>

</html>

附-以浏览器最外层body/html的滚动条为例子代码

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
		body {
			background-color: #ccc;
		}

		.target {
			width: 60px;
			height: 60px;
			background-color: red;
		}
	</style>
</head>

<body>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<h1>孙悟空</h1>
	<div class="target"></div>
	<script>
		window.onload = () => {
			let targetDom = document.querySelector('.target') // 目标元素dom
			function callBack() {
				const top = targetDom.getBoundingClientRect().top; // 目标元素dom距离顶部的高度
				if (top <= window.innerHeight) { // 当top小于等于文档显示区域的高时,就进入可视区域了
					console.log('在可视区域');
					document.body.style.background = 'pink'
				} else {
					console.log('不在可视区域'); // 当top大于文档显示区域的高时,就离开可视区域了
					document.body.style.background = '#ccc'
				}
			}
			window.addEventListener('scroll', callBack);
		}
	</script>
</body>

</html>