跳到主要内容

可视检测

2023年02月23日
柏拉文
越努力,越幸运

一、IntersectionObserve


1.1 核心

元素即将可见: threshold: 0

元素完全可见: threshold: 1

1.2 语法

const targetDom = document.querySelector(".box");
const intersectionObserverOption = {
threshold: 0,
};

function intersectionObserverCallback(entries, observer) {
entries.forEach((entry) => {
if (entry.isIntersecting) {
observer.unobserve(entry.target);
console.log("元素可见");
}
});
}

const intersectionObserver = new IntersectionObserver(
intersectionObserverCallback,
intersectionObserverOption
);
intersectionObserver.observe(targetDom);

二、Scroll、getBoundingClientRect


2.1 核心

元素即将可见

const { top,right,bottom,left } = target.getBoundingClientRect(); 

return top >= 0 && left >= 0 && right <= viewPortWidth && top <= viewProtHeight;

元素完全可见

const { top,right,bottom,left } = target.getBoundingClientRect(); 

return top >= 0 && left >= 0 && right <= viewPortWidth && bottom <= viewProtHeight;

2.2 语法

const targetDom = document.querySelector(".box");

function throttle(fn, wait) {
let timer = null;
return function (...args) {
const context = this;
if (!timer) {
timer = setTimeout(() => {
clearTimeout(timer);
timer = null;
fn.apply(context, args);
}, wait);
}
};
}

function isVisible(
boundingClientRect,
viewPortWidth,
viewProtHeight,
threshold
) {
const { top, right, bottom, left } = boundingClientRect;
if (threshold) {
return (
top >= 0 &&
left >= 0 &&
right <= viewPortWidth &&
bottom <= viewProtHeight
);
}
return (
top >= 0 &&
left >= 0 &&
right <= viewPortWidth &&
top <= viewProtHeight
);
}

function handleScroll() {
const boundingClientRect = targetDom.getBoundingClientRect();
const viewPortWidth =
window.innerWidth ||
document.documentElement.clientWidth ||
document.body.clientWidth;
const viewPortHeight =
window.innerHeight ||
document.documentElement.clientHeight ||
document.body.clientHeight;
const visible = isVisible(
boundingClientRect,
viewPortWidth,
viewPortHeight,
true
);
console.log(visible);
}

window.addEventListener("scroll", throttle(handleScroll, 80));

三、Scroll、OffsetTop、OffsetHeight


3.1 核心

元素可见: viewPortHeight + viewportScrollTop >= targetDomOffsetTop

3.2 语法

const targetDom = document.querySelector(".box");

function throttle(fn, wait) {
let timer = null;
return function (...args) {
const context = this;
if (!timer) {
timer = setTimeout(() => {
clearTimeout(timer);
timer = null;
fn.apply(context, args);
}, wait);
}
};
}

function isVisible(
viewPortHeight,
viewportScrollTop,
targetDomOffsetTop
) {
return viewPortHeight + viewportScrollTop >= targetDomOffsetTop;
}

function handleScroll() {
const viewPortHeight =
window.innerHeight ||
document.documentElement.clientHeight ||
document.body.clientHeight;
const viewportScrollTop =
document.documentElement.scrollTop ||
window.pageYOffset ||
document.body.scrollTop;
const targetOffsetTop = targetDom?.offsetTop || 0;
const visible = isVisible(
viewPortHeight,
viewportScrollTop,
targetOffsetTop
);
console.log(visible);
}

window.addEventListener("scroll", throttle(handleScroll,80));

参考资料