如何判斷一個(gè)元素是否在可視區(qū)域中?
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
一、用途可視區(qū)域即我們?yōu)g覽網(wǎng)頁(yè)的設(shè)備肉眼可見(jiàn)的區(qū)域,如下圖
在日常開(kāi)發(fā)中,我們經(jīng)常需要判斷目標(biāo)元素是否在視窗之內(nèi)或者和視窗的距離小于一個(gè)值(例如 100 px),從而實(shí)現(xiàn)一些常用的功能,例如:
二、實(shí)現(xiàn)方式判斷一個(gè)元素是否在可視區(qū)域,我們常用的有三種辦法:
offsetTop、scrollTop
下面再來(lái)了解下
這里可以看到 最后,關(guān)于
注意
下面再看看如何實(shí)現(xiàn)判斷: 公式如下: el.offsetTop - document.documentElement.scrollTop <= viewPortHeight 代碼實(shí)現(xiàn): function isInViewPortOfOne (el) {
// viewPortHeight 兼容所有瀏覽器寫(xiě)法
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返回值是一個(gè) const target = document.querySelector('.target');
const clientRect = target.getBoundingClientRect();
console.log(clientRect);
// {
// bottom: 556.21875,
// height: 393.59375,
// left: 333,
// right: 1017,
// top: 162.625,
// width: 684
// }屬性對(duì)應(yīng)的關(guān)系圖如下所示:
當(dāng)頁(yè)面發(fā)生滾動(dòng)的時(shí)候, 如果一個(gè)元素在視窗之內(nèi)的話,那么它一定滿足下面四個(gè)條件:
實(shí)現(xiàn)代碼如下: 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
);
}Intersection Observer
使用步驟主要分為兩步:創(chuàng)建觀察者和傳入被觀察者 創(chuàng)建觀察者const options = {
// 表示重疊面積占被觀察者的比例,從 0 - 1 取值,
// 1 表示完全被包含
threshold: 1.0,
root:document.querySelector('#scrollArea') // 必須是目標(biāo)元素的父級(jí)元素
};
const callback = (entries, observer) => { ....}
const observer = new IntersectionObserver(callback, options);通過(guò) 關(guān)于 // 上段代碼中被省略的 callback
const callback = function(entries, observer) {
entries.forEach(entry => {
entry.time; // 觸發(fā)的時(shí)間
entry.rootBounds; // 根元素的位置矩形,這種情況下為視窗位置
entry.boundingClientRect; // 被觀察者的位置舉行
entry.intersectionRect; // 重疊區(qū)域的位置矩形
entry.intersectionRatio; // 重疊區(qū)域占被觀察者面積的比例(被觀察者不是矩形時(shí)也按照矩形計(jì)算)
entry.target; // 被觀察者
});
};傳入被觀察者通過(guò) const target = document.querySelector('.target');
observer.observe(target);三、案例分析實(shí)現(xiàn):創(chuàng)建了一個(gè)十萬(wàn)個(gè)節(jié)點(diǎn)的長(zhǎng)列表,當(dāng)節(jié)點(diǎn)滾入到視窗中時(shí),背景就會(huì)從紅色變?yōu)辄S色
<div class="container"></div>
.container {
display: flex;
flex-wrap: wrap;
}
.target {
margin: 5px;
width: 20px;
height: 20px;
background: red;
}往 const $container = $(".container");
// 插入 100000 個(gè) <div class="target"></div>
function createTargets() {
const htmlString = new Array(100000)
.fill('<div class="target"></div>')
.join("");
$container.html(htmlString);
}這里,首先使用 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;
}然后開(kāi)始監(jiān)聽(tīng) $(window).on("scroll", () => {
console.log("scroll !");
$targets.each((index, element) => {
if (isInViewPort(element)) {
$(element).css("background-color", "yellow");
}
});
});通過(guò)上述方式,可以看到可視區(qū)域顏色會(huì)變成黃色了,但是可以明顯看到有卡頓的現(xiàn)象,原因在于我們綁定了 下面通過(guò) 首先創(chuàng)建一個(gè)觀察者 const observer = new IntersectionObserver(getYellow, { threshold: 1.0 });
function getYellow(entries, observer) {
entries.forEach(entry => {
$(entry.target).css("background-color", "yellow");
});
}最后傳入觀察者,即 $targets.each((index, element) => {
observer.observe(element);
});可以看到功能同樣完成,并且頁(yè)面不會(huì)出現(xiàn)卡頓的情況 轉(zhuǎn)自https://www.cnblogs.com/smileZAZ/p/18216096 該文章在 2025/10/14 15:21:57 編輯過(guò) |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |