js如何對元素可視區(qū)域進(jìn)行判定
前言
在前端開發(fā)中,有時(shí)候我們需要判斷一個(gè)元素是否在可視區(qū)域內(nèi),比如實(shí)現(xiàn)懶加載、曝光統(tǒng)計(jì)、動(dòng)畫效果等功能。那么,如何對進(jìn)行元素可視區(qū)域的判定呢?本文將介紹幾種常用的方法,并分析它們的優(yōu)缺點(diǎn)。
方案介紹
使用 getBoundingClientRect
getBoundingClientRect 是一個(gè) DOM API,它返回一個(gè)對象,包含了元素的左、右、上、下、寬、高等屬性,這些屬性都是相對于視口的。根據(jù)該對象返回值可以通過以下條件判斷元素是否在可視范圍內(nèi):
- 當(dāng) DOMRect.top 小于視口高度 且 DOmRect.bottom 大于0
- 當(dāng) DOMRect.left 小于視口寬度 且 DOmRect.right 大于0
這種方法的優(yōu)點(diǎn)是簡單易用,不需要考慮滾動(dòng)條的影響,也不需要獲取元素的尺寸和位置。缺點(diǎn)是兼容性不太好,IE8 及以下不支持該 API。
function isInViewport(element) { const rect = element.getBoundingClientRect(); return ( rect.top < window.innerHeight && rect.bottom > 0 && rect.left < window.innerWidth && rect.right > 0 ); }
使用 scrollTop 與 offsetTop
scrollTop 是一個(gè)屬性,表示元素滾動(dòng)條向下滾動(dòng)的距離。offsetTop 是一個(gè)屬性,表示元素相對于其最近的定位父元素的頂部偏移量。通過這兩個(gè)屬性,我們可以計(jì)算出元素相對于文檔的頂部偏移量,然后再與視口高度和滾動(dòng)條位置進(jìn)行比較,判斷元素是否在可視區(qū)域內(nèi):
- 當(dāng) 元素距文檔頂部距離 - 滾動(dòng)條位置 < 視口高度 且 元素距文檔頂部距離 - 滾動(dòng)條位置 + 元素高度 > 0
- 當(dāng) 元素距文檔左側(cè)距離 - 滾動(dòng)條位置 < 視口寬度 且 元素距文檔左側(cè)距離 - 滾動(dòng)條位置 + 元素寬度 > 0
這種方法的優(yōu)點(diǎn)是兼容性好,可以支持 IE8 及以上瀏覽器。缺點(diǎn)是需要考慮滾動(dòng)條的影響,也需要獲取元素的尺寸和位置,比較繁瑣。
function isInViewport(element) { const scrollTop = document.documentElement.scrollTop || document.body.scrollTop; const offsetTop = element.offsetTop; const windowHeight = window.innerHeight; const elementHeight = element.offsetHeight; return ( offsetTop - scrollTop < windowHeight && offsetTop - scrollTop + elementHeight > 0 ); }
使用 IntersectionObserver
IntersectionObserver 是一個(gè)新的 API,它可以用來監(jiān)聽元素與其祖先元素或視口的交叉情況。它接受一個(gè)回調(diào)函數(shù)和一個(gè)配置對象作為參數(shù),回調(diào)函數(shù)會(huì)在每次元素交叉狀態(tài)發(fā)生變化時(shí)被調(diào)用,配置對象可以指定觀察的根元素、根邊界和閾值。通過這個(gè) API,我們可以輕松地判斷元素是否在可視區(qū)域內(nèi) :
- 創(chuàng)建一個(gè) IntersectionObserver 實(shí)例,并傳入一個(gè)回調(diào)函數(shù)和一個(gè)配置對象
- 在回調(diào)函數(shù)中,根據(jù) entries 參數(shù)獲取每個(gè)被觀察元素的交叉信息
- 判斷每個(gè)被觀察元素的 isIntersecting 屬性是否為 true,如果是,則表示元素在可視區(qū)域內(nèi)
function isInViewport(element) { const observer = new IntersectionObserver( ([entry]) => { return entry.isIntersecting; }, { root: null, rootMargin: '0px', threshold: 0, } ); observer.observe(element); }
注意事項(xiàng)
- 元素可視區(qū)域的判定需要在滾動(dòng)事件觸發(fā)時(shí)進(jìn)行,否則無法及時(shí)更新元素的狀態(tài)。
- 不同的判定方法可能會(huì)受到一些特殊情況的影響,例如元素的定位方式、元素與祖先元素的滾動(dòng)條、元素的顯示狀態(tài)等。因此需要在實(shí)際使用時(shí)進(jìn)行測試和驗(yàn)證。
- 當(dāng)需要同時(shí)監(jiān)聽多個(gè)元素的可視狀態(tài)時(shí),可以考慮使用
IntersectionObserver
來提高性能。 - 當(dāng)需要進(jìn)行復(fù)雜的可視區(qū)域判定時(shí),可以考慮使用第三方庫或框架來簡化操作,例如
react-intersection-observer
、scrollama
等。 - 在進(jìn)行元素的可視區(qū)域判定時(shí),需要避免頻繁地操作 DOM 和觸發(fā)回流和重繪,否則會(huì)影響頁面性能??梢酝ㄟ^防抖或節(jié)流等方式進(jìn)行優(yōu)化。
到此這篇關(guān)于js如何對元素可視區(qū)域進(jìn)行判定的文章就介紹到這了,更多相關(guān)js 元素可視區(qū)域判定內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
HTML5+Canvas調(diào)用手機(jī)拍照功能實(shí)現(xiàn)圖片上傳(上)
這篇文章主要為大家詳細(xì)介紹了HTML5+Canvas,和jquery技術(shù),調(diào)用手機(jī)拍照功能實(shí)現(xiàn)圖片上傳,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04easyUI實(shí)現(xiàn)(alert)提示框自動(dòng)關(guān)閉的實(shí)例代碼
下面小編就為大家?guī)硪黄猠asyUI實(shí)現(xiàn)(alert)提示框自動(dòng)關(guān)閉的實(shí)例代碼。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-11-11JS判斷元素是否在數(shù)組內(nèi)的實(shí)現(xiàn)代碼
這篇文章主要介紹了JS判斷元素是否在數(shù)組內(nèi)的實(shí)現(xiàn)代碼,需要的朋友可以參考下2016-03-03簡單實(shí)現(xiàn)js選項(xiàng)卡切換效果
這篇文章主要為大家介紹了簡單實(shí)現(xiàn)js選項(xiàng)卡切換效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-02-02javascript中萬惡的function實(shí)例分析
javascript中萬惡的function實(shí)例分析,學(xué)習(xí)js的朋友可以參考下。2011-05-05js實(shí)現(xiàn)會(huì)跳動(dòng)的日歷效果(完整實(shí)例)
下面小編就為大家?guī)硪黄猨s實(shí)現(xiàn)會(huì)跳動(dòng)的日歷效果(完整實(shí)例)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10值得分享和收藏的Bootstrap學(xué)習(xí)教程
這絕對是一套值得分享和大家收藏的Bootstrap學(xué)習(xí)教程,完整的知識體系,系統(tǒng)的學(xué)習(xí)資料,幫助大家開啟Bootstrap學(xué)習(xí)之旅,享受Bootstrap帶給大家的奇妙樂趣2016-05-05