JavaScript判斷元素是否在可視區(qū)域的三種方法
方法1:getBoundingClientRect
用法
let domRect = dom.getBoundingClientRect();
DOMRect:{ x/left:視圖原點(diǎn)(左上角)距離dom左邊框距離, y/top:視圖原點(diǎn)(左上角)距離dom上邊框距離, right:視圖原點(diǎn)(左上角)距離dom右邊框距離, bottom:視圖原點(diǎn)(左上角)距離dom底邊框距離, width:dom的寬度,標(biāo)準(zhǔn)盒模型,width = 寬度+padding+border;怪異盒模型,width = 設(shè)置的寬度, height:dom的高度, }
所以我們可以根據(jù)DOMRect
的中的各個(gè)屬性來(lái)判斷dom
是否在可視區(qū)域內(nèi)。
eg:
<!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>getBoundingClientRect可視區(qū)域</title> <style> * { margin: 0 } .circle-wrap { position: fixed; top: 50px; right: 50px; padding: 10px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); width: 140px; background: #fff; } .circle-wrap .circle { display: inline-block; width: 20px; height: 20px; border-radius: 50%; background: red; } .card-wrap { height: 2000px; width: 3000px; margin-top: 100px; } .card-wrap .card { width: 200px; height: 200px; padding: 20px; box-sizing: border-box; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); margin-top: 500px; margin-left: 500px; } </style> </head> <body> <div class="circle-wrap"> <span>當(dāng)下方的卡片在可視區(qū)域內(nèi),我的圈圈是綠色,否則是紅色</span> <span class="circle"></span> </div> <div class="card-wrap"> <div class="card">我是一個(gè)卡片</div> </div> <script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.20/lodash.js"></script> <script> const card = document.querySelector(".card"); const circle = document.querySelector(".circle"); const getBoundingClientRectJudge = () => { let domRect = card.getBoundingClientRect(); console.log(domRect) let ch = document.documentElement.clientHeight; let cw = document.documentElement.clientWidth; let isInsert = true; if (domRect.bottom < 0 || domRect.top > ch || domRect.right < 0 || domRect.left > cw) { isInsert = false; } let background = null if (isInsert) { background = "green" } else { background = "red" } circle.style.background = background } window.addEventListener("scroll", _.throttle(getBoundingClientRectJudge, 500)) getBoundingClientRectJudge() </script> </body> </html>
效果圖:
問(wèn)題
getBoundingClientRect
并不能滿足所有情況,甚至說(shuō),它只能滿足一種情況的判斷,那就是需要判斷的那個(gè)dom
節(jié)點(diǎn),它只身處在一個(gè)滾動(dòng)條的情況下。什么意思呢,就是它所有的祖先節(jié)點(diǎn),加起來(lái)的滾動(dòng)條只有1個(gè),如果它父節(jié)點(diǎn)有滾動(dòng)條,父父節(jié)點(diǎn)也有滾動(dòng)條,那這種方法就不好用了,請(qǐng)看示例:
下面展示的結(jié)果是錯(cuò)誤的,圈圈應(yīng)該是紅色才對(duì)。
<!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>getBoundingClientRect可視區(qū)域</title> <style> * { margin: 0 } body { height: 2000px; width: 3000px; } .circle-wrap { position: fixed; top: 50px; right: 50px; padding: 10px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); width: 140px; background: #fff; } .circle-wrap .circle { display: inline-block; width: 20px; height: 20px; border-radius: 50%; background: red; } .card-wrap { height: 400px; width: 600px; margin-top: 100px; margin-left: 100px; border: 1px solid green; overflow: auto; } .card-wrap .card { width: 200px; height: 200px; padding: 20px; box-sizing: border-box; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); margin-top: 500px; margin-left: 500px; } .head { width: 100%; height: 100px; background: pink; /* position: fixed; */ top: 0; left: 0; } </style> </head> <body> <!-- <div class="head"></div> --> <div class="circle-wrap"> <span>當(dāng)下方的卡片在可視區(qū)域內(nèi),我的圈圈是綠色,否則是紅色</span> <span class="circle"></span> </div> <div class="card-wrap"> <div class="card">我是一個(gè)卡片</div> </div> <script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.20/lodash.js"></script> <script> const card = document.querySelector(".card"); const circle = document.querySelector(".circle"); const getBoundingClientRectJudge = () => { let domRect = card.getBoundingClientRect(); let ch = document.documentElement.clientHeight; let cw = document.documentElement.clientWidth; let isInsert = true; if (domRect.bottom < 0 || domRect.top > ch || domRect.right < 0 || domRect.left > cw) { isInsert = false; } let background = null if (isInsert) { background = "green" } else { background = "red" } circle.style.background = background } window.addEventListener("scroll", _.throttle(getBoundingClientRectJudge, 500)) getBoundingClientRectJudge() </script> </body> </html>
由此,我們引出第二種方法,IntersectionObserver。
方法2:IntersectionObserver
用法
eg:
<!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>getBoundingClientRect可視區(qū)域</title> <style> * { margin: 0 } body { height: 2000px; width: 3000px; } .circle-wrap { position: fixed; top: 50px; right: 50px; padding: 10px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); width: 140px; background: #fff; } .circle-wrap .circle { display: inline-block; width: 20px; height: 20px; border-radius: 50%; background: red; } .card-wrap { height: 400px; width: 600px; margin-top: 100px; margin-left: 100px; border: 1px solid green; overflow: auto; } .card-wrap .card { width: 200px; height: 200px; padding: 20px; box-sizing: border-box; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); margin-top: 500px; margin-left: 500px; } .head{ width: 100%; height: 100px; background: pink; /* position: fixed; */ top:0; left: 0; } </style> </head> <body> <!-- <div class="head"></div> --> <div class="circle-wrap"> <span>當(dāng)下方的卡片在可視區(qū)域內(nèi),我的圈圈是綠色,否則是紅色</span> <span class="circle"></span> </div> <div class="card-wrap"> <div class="card">我是一個(gè)卡片</div> </div> <script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.20/lodash.js"></script> <script> const card = document.querySelector(".card"); const circle = document.querySelector(".circle"); const observer = new IntersectionObserver((changes) => { // changes是數(shù)組 changes.forEach(one => { console.log(one) let isIntersecting = one.isIntersecting let background = null if (isIntersecting) { background = "green" } else { background = "red" } circle.style.background = background }) }) observer.observe(card) // console.log(observer) /* 取消觀察特定的元素:observer.unobserve(dom) */ /* 對(duì)象停止監(jiān)聽(tīng)目標(biāo) observer.disconnect() */ </script> </body> </html>
補(bǔ)充說(shuō)明
IntersectionObserver
可以傳root
,進(jìn)一步判斷dom
是相對(duì)于哪個(gè)節(jié)點(diǎn),來(lái)判斷是否在可視區(qū)域內(nèi),默認(rèn)root
是document
。
const observer = new IntersectionObserver((changes) => { console.log(changes) changes.forEach(one => { console.log(one) let isIntersecting = one.isIntersecting let background = null if (isIntersecting) { background = "green" } else { background = "red" } circle.style.background = background }) },{root:document.querySelector(".card-wrap")})
方法3:offsetTop、scrollTop
說(shuō)明
offsetTop
:元素的上外邊框至包含元素的上內(nèi)邊框之間的像素距離,其他方向相同offsetWidth
:元素兩端算上外邊框的寬度,其他方向相同scrollLeft
和scrollTop
:既可以確定當(dāng)前元素的滾動(dòng)狀態(tài),也可以設(shè)置元素的滾動(dòng)位置scrollWidth
和scrollHeight
:確定元素內(nèi)容的實(shí)際大小clientWidth
:元素內(nèi)容區(qū)寬度加上左右內(nèi)邊距寬度,即clientWidth = content + padding
clientHeight
:元素內(nèi)容區(qū)高度加上上下內(nèi)邊距高度,即clientHeight = content + padding
使用
公式:
0 <= el.offsetTop - document.documentElement.scrollTop <= viewPortHeight
寫(xiě)法:
function isInViePortOfOne(el){ const viewPortHeight = window.innerHeight || document.documentElement.clientHeight||document.body.clientHeight const offsetTop = el.offsetTop; const scollTop = document.documentElement.scrollTop const top = offsetTop - scollTop; return top <= viewPortHeight && top >= 0 }
以上就是JavaScript判斷元素是否在可視區(qū)域的三種方法的詳細(xì)內(nèi)容,更多關(guān)于JavaScript判斷元素是否在可視區(qū)域的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
javascript十個(gè)最常用的自定義函數(shù)(中文版)
如果不使用類(lèi)庫(kù)或者沒(méi)有自己的類(lèi)庫(kù),儲(chǔ)備一些常用函數(shù)總是有好處的。2009-09-09JS實(shí)現(xiàn)的數(shù)組全排列輸出算法
這篇文章主要介紹了JS實(shí)現(xiàn)的數(shù)組全排列輸出算法,實(shí)例分析了全排列的原理與相關(guān)的javascript實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03一款好用的移動(dòng)端滾動(dòng)插件BetterScroll
BetterScroll 是一款重點(diǎn)解決移動(dòng)端各種滾動(dòng)場(chǎng)景需求的開(kāi)源插件,用于滾動(dòng)列表、選擇器、輪播圖、索引列表、開(kāi)屏引導(dǎo)等應(yīng)用場(chǎng)景,感興趣的一起來(lái)了解一下2021-09-096種JavaScript判斷對(duì)象自身為空的方法小結(jié)
這篇文章主要為大家詳細(xì)介紹了6種JavaScript判斷對(duì)象自身為空的方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12ES6(ECMAScript 6)新特性之模板字符串用法分析
這篇文章主要介紹了ES6(ECMAScript 6)新特性之模板字符串用法,簡(jiǎn)單介紹了ES6模板字符串的概念、功能并結(jié)合實(shí)例形式分析了ES6模板字符串的用法,需要的朋友可以參考下2017-04-04微信小程序?qū)崿F(xiàn)注冊(cè)登錄功能(表單校驗(yàn)、錯(cuò)誤提示)
這篇文章主要介紹了微信小程序 實(shí)現(xiàn)注冊(cè)、登錄功能(表單校驗(yàn)、錯(cuò)誤提示),本文通過(guò)代碼給大家詳細(xì)介紹,需要的朋友可以參考下2019-12-12