说说如何判断一个元素在可视区域内
# 是什么
可视区域: 浏览器中肉眼能看到的区域
# 常见应用
- 图片懒加载
- 列表无限滚动
- 计算广告的曝光情况
- 可点击链接的预加载
# 实现方式
- offsetTop scrollTop
- getBoundingClientRect
- intersection Obsever(用的不多)
# offsetTop scrollTop
- clientWidth = content + padding
- clientHeight = content + padding
- 不包括 margin 和 border
function isInViewPortOfOne(el) {
// viewPortHeight 兼容所有浏览器写法
const viewPortHeight =
window.innerHeight ||
document.documentElement.clientHeight ||
document.body.clientHeight;
const offsetTop = el.offsetTop;
const scrollTop = document.documentElement.scrollTop;
const top = offsetTop - scrollTop;
return top <= viewPortHeight;
}
# getBoundingClientRect
- top 元素顶部到可视区域顶部距离
- bottom 元素底部到可视区域顶部距离
$0.getBoundingClientRect();
bottom: 252;
height: 50;
left: 106;
right: 960;
top: 202;
width: 854;
x: 106;
- 可视条件
- top 大于等于 0
- left 大于等于 0
- bottom 小于等于视窗高度
- right 小于等于视窗宽度
function isInViewPort(element) {
const viewWidth = window.innerWidth || document.documentElement.clientWidth;
const viewHeight =
window.innerHeight || document.documentElement.clientHeight;
const { top, right, bottom, left } = element.getBoundingClientRect();
return top >= 0 && left >= 0 && right <= viewWidth && bottom <= viewHeight;
}
# 案例
插入 10 万长列表,滚动颜色变黄
<style>
.container {
display: flex;
flex-wrap: wrap;
}
.target {
margin: 5px;
width: 20px;
height: 20px;
background: red;
}
</style>
<div class="container"></div>
<script>
const $container = $(".container");
function createTagets() {
const htmls = new Array(10000).fill('<div class="target"></div>').join("");
$container.html(htmls);
}
function isInViewPort(element) {
const viewWidth = window.innerWidth || document.documentElement.clientWidth;
const viewHeight =
window.innerHeight || document.documentElement.clientHeight;
const { top, right, bottom, left } = element.getBoundingClientRect();
return top >= 0 && left >= 0 && right <= viewWidth && bottom <= viewHeight;
}
createTagets();
const targets = $(".target");
$(window).on("scroll", () => {
// 避免卡顿
window.requestAnimationFrame(() => {
targets.each((index, ele) => {
if (isInViewPort(ele)) {
$(ele).css("background-color", "yellow");
} else {
$(ele).css("background-color", "red");
}
});
});
});
</script>
上次更新: 2021/12/19, 18:05:42