国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

如何判斷元素是否在可視區(qū)域ViewPort

xiguadada / 2000人閱讀

摘要:在這里一次性做個(gè)總結(jié),以用來判斷元素是否在可視區(qū)域以及用原生簡單實(shí)現(xiàn)懶加載。被隱藏在內(nèi)容區(qū)域左側(cè)的像素?cái)?shù)。比如上篇文章文字跑馬燈項(xiàng)目中的使用戳此跳轉(zhuǎn)小結(jié)只讀屬性,不包括滾動(dòng)條。

個(gè)性簽名: 生如夏花,逝如冬雪;人生如此,何悔何怨。

前言: 經(jīng)常需要計(jì)算元素的大小或者所在頁面的位置,offsetWidth,clientWidth,scrollWidth,scrollTop這幾個(gè)關(guān)鍵字的出現(xiàn)更是家常便飯,每次碰到都需要事先實(shí)驗(yàn)一番。為了下次開發(fā)提高效率。在這里一次性做個(gè)總結(jié),以用來判斷元素是否在可視區(qū)域以及用原生js簡單實(shí)現(xiàn)懶加載。文末有個(gè)簡單的懶加載實(shí)現(xiàn)的demo,有需要的可以看一下。

目錄

工欲善其事,必先利其器。在判斷元素是否在可視區(qū)域?qū)崿F(xiàn)簡單的原生懶加載前,我們先簡單回顧下以下幾個(gè)關(guān)鍵的概念。

ps: 如果你對(duì)這些概念已經(jīng)比較熟悉了,可以直接跳到第五點(diǎn)查看關(guān)鍵代碼示例。

1. 偏移量

偏移量(offset dimension),元素的可見大小由其高度、寬度決定,包括所有內(nèi)邊距、滾動(dòng)條和邊框大小(注意,不包括外邊距)。通過下列4個(gè)屬性可以取得元素的偏移量。

偏移量 概念 公式
offsetHeight 元素在垂直方向上占用的空間大小,以像素計(jì)。包括元素的高度、(可見的) 水平滾動(dòng)條的高度、上邊框高度和下邊框高度。 offsetHeght = content + padding + border + scrollX
offsetWidth 元素在水平方向上占用的空間大小,以像素計(jì)。包括元素的寬度、(可見的)垂 直滾動(dòng)條的寬度、左邊框?qū)挾群陀疫吙驅(qū)挾取?/td> offsetWidth = content + padding + border + scrollY
offsetLeft 元素的左外邊框至**包含元素的左內(nèi)邊框之間的像素距離。
offsetTop 元素的上外邊框至包含元素的上內(nèi)邊框之間的像素距離。

其中,offsetLeft 和 offsetTop 屬性與包含元素有關(guān),包含元素的引用保存在 offsetParent 屬性中。**offsetParent 屬性不一定與 parentNode 的值相等。

如下圖顯示

注意: 所有這些偏移量屬性都是只讀的,而且每次訪問它們都需要重新計(jì)算。因此,應(yīng)該盡量避免重復(fù)訪問這些屬性;如果需要重復(fù)使用其中某些屬性的值,可以將它們保 存在局部變量中,以提高性能。

這也是上篇文章文字跑馬燈項(xiàng)目中(戳此跳轉(zhuǎn)),為什么增加padding后,textWidth需要重新獲取的原因

小結(jié)

偏移量: 只讀屬性;包括滾動(dòng)條和邊框,不包括外邊距。

2. 客戶區(qū)大小

客戶區(qū)大小是只讀的,每次訪問都要重新計(jì)算的。

客戶區(qū)大小 概念 公式
clientWidth clientWidth 屬性是元素內(nèi)容區(qū)寬度加 上左右內(nèi)邊距寬度; clientWidth = content + padding
clientHeight 元素內(nèi)容區(qū)高度加上上下內(nèi)邊距高度 clientHeight = content + padding

最常用到這些屬性的情況,就是確定瀏覽器視口大小的時(shí)候(在 IE7 之前的版本中)。如下面的例子所示:

function getViewport(){
    // 檢查 document.compatMode 屬性,以確定瀏覽器是否運(yùn)行在混雜模式。
    // Safari3.1 之前的版本不支持這個(gè)屬性,因此就會(huì)自動(dòng)執(zhí)行 else 語句
    if (document.compatMode == "BackCompat"){
        return {
            width: document.body.clientWidth,
            height: document.body.clientHeight
        };
    } else {
        return {
            width: document.documentElement.clientWidth,
            height: document.documentElement.clientHeight
        }; 
    }
}

小結(jié)

客戶區(qū)大小: 只讀屬性;不包括滾動(dòng)條和邊框,不包括外邊距。

3. 滾動(dòng)大小
概念
scrollHeight 在沒有滾動(dòng)條的情況下,元素內(nèi)容的總高度。
scrollWidth 在沒有滾動(dòng)條的情況下,元素內(nèi)容的總寬度。
scrollLeft 被隱藏在內(nèi)容區(qū)域左側(cè)的像素?cái)?shù)。通過設(shè)置這個(gè)屬性可以改變?cè)氐臐L動(dòng)位置。
scrollTop 被隱藏在內(nèi)容區(qū)域上方的像素?cái)?shù)。通過設(shè)置這個(gè)屬性可以改變?cè)氐臐L動(dòng)位置。

scrollWidth 和 scrollHeight 主要用于確定元素內(nèi)容的實(shí)際大小。

scrollLeft 和 scrollTop屬性既可以確定元素當(dāng)前滾動(dòng)的狀態(tài),也可以設(shè)置元素的滾動(dòng)位 置。在元素尚未被滾動(dòng)時(shí),這兩個(gè)屬性的值都等于 0。如果元素被垂直滾動(dòng)了,那么 scrollTop 的值 會(huì)大于 0,且表示元素上方不可見內(nèi)容的像素高度。如果元素被水平滾動(dòng)了,那么 scrollLeft 的值會(huì) 大于 0,且表示元素左側(cè)不可見內(nèi)容的像素寬度。這兩個(gè)屬性都是可以設(shè)置的,因此將元素的 scrollLeft 和 scrollTop 設(shè)置為 0,就可以重置元素的滾動(dòng)位置。比如:上篇文章文字跑馬燈項(xiàng)目中scrollLeft的使用(戳此跳轉(zhuǎn))

小結(jié)

只讀屬性,不包括滾動(dòng)條、border。

4. 確定元素大小

getBoundingClientRect

getBoundingClientRect的兼容性寫法:

對(duì)于不支持 getBoundingClientRect()的瀏覽器,可以通過其他手段取得相同的信息。一般來 說,right 和 left 的差值與 offsetWidth 的值相等,而 bottom 和 top 的差值與 offsetHeight 相等。綜合上述,就可以創(chuàng)建出下面這個(gè)跨瀏覽器的函數(shù):

function getElementLeft(element){
    var actualLeft = element.offsetLeft;
    var current = element.offsetParent;
    while (current !== null){
        actualLeft += current.offsetLeft;
        current = current.offsetParent;
    }
    return actualLeft;
}

function getElementTop(element){
    var actualTop = element.offsetTop;
    var current = element.offsetParent;
    while (current !== null){
        actualTop += current. offsetTop;
        current = current.offsetParent;
    }
    return actualTop;
}

function getBoundingClientRect(element) {
    var scrollTop = document.documentElement.scrollTop;
    var scrollLeft = document.documentElement.scrollLeft;
    if (element.getBoundingClientRect) {
        if (typeof arguments.callee.offset != "number") {
            var temp = document.createElement("div");
            temp.style.cssText = "position:absolute;left:0;top:0;"; document.body.appendChild(temp);
            arguments.callee.offset = -temp.getBoundingClientRect().top - scrollTop; document.body.removeChild(temp);
            temp = null;
        }
        var rect = element.getBoundingClientRect();
        var offset = arguments.callee.offset;
        return {
            left: rect.left + offset,
            right: rect.right + offset,
            top: rect.top + offset,
            bottom: rect.bottom + offset
        };
    } else {
        var actualLeft = getElementLeft(element);
        var actualTop = getElementTop(element);
        return {
            left: actualLeft - scrollLeft,
            right: actualLeft + element.offsetWidth - scrollLeft,
            top: actualTop - scrollTop,
            bottom: actualTop + element.offsetHeight - scrollTop
        }
    }
}
5.判斷元素是否在可視區(qū)域

知道了元素的大小以及所位于的區(qū)域外,我們可以做些什么呢?我們可以通過上面學(xué)到的知識(shí)點(diǎn)來檢測元素是否在可視區(qū)域,再說大一點(diǎn),這也是懶加載圖片的實(shí)現(xiàn)原理。

5.1 第一種方法

公式: el.offsetTop - document.documentElement.scrollTop <= viewPortHeight

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
    console.log("top", top)
     // 這里有個(gè)+100是為了提前加載+ 100
    return top <= viewPortHeight + 100
}
5.2 第二種方法

公式: el.getBoundingClientReact().top <= viewPortHeight

其實(shí), el.offsetTop - document.documentElement.scrollTop = el.getBoundingClientRect().top, 利用這點(diǎn),我們可以用下面代碼代替方法一

function isInViewPortOfTwo (el) {
    const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight 
    const top = el.getBoundingClientRect() && el.getBoundingClientRect().top
    console.log("top", top)
    return top  <= viewPortHeight + 100
}
5.3 第三種方法

公式: intersectionRatio > 0 && intersectionRatio <= 1

// 定義一個(gè)交叉觀察器
const io = new IntersectionObserver(ioes => {
    ioes.forEach(ioe => {
        const el = ioe.target
        const intersectionRatio = ioe.intersectionRatio
        if (intersectionRatio > 0 && intersectionRatio <= 1) {
            loadImg(el)
            io.unobserve(el)
        }
         el.onload = el.onerror = () => io.unobserve(el)
    })
})
// 執(zhí)行交叉觀察器
function isInViewPortOfThree (el) {
    io.observe(el)
}
5.4 兼容性比較

在兼容性方面,我們知道越原始的方法兼容性是最好的,那么第二種方法和第三種方法能否代替第三種方法呢?我們來看看。

從caniuse的數(shù)據(jù)來看,getBoundingClientReact的適配情況很樂觀了。

所以,如果在移動(dòng)端和桌面端都要做兼容適配的話,方法二完全可以代替方法一進(jìn)行適配了。如果僅僅是桌面端適配(比如運(yùn)營后臺(tái)),我們或許可以嘗試下新的IntersectionObserver方法,畢竟IntersectionObserver里面還有更多豐富的功能等著我們?nèi)ンw驗(yàn)?zāi)亍?/p> 5.5 實(shí)例

有時(shí),我們希望某些靜態(tài)資源(比如圖片),只有用戶向下滾動(dòng),它們進(jìn)入視口時(shí)才加載,這樣可以節(jié)省帶寬,提高網(wǎng)頁性能。這就叫做"惰性加載",也稱為懶加載。

惰性加載預(yù)覽DEMO(放入你的本地圖片即可通過更換不同方法實(shí)現(xiàn)懶加載)

------------------------------ 華麗的分割線 ---------------------------

ps: 有公眾號(hào)大佬想減輕日常寫推文的時(shí)間消耗,收購技術(shù)原創(chuàng)文章的稿子放在自己公眾號(hào)展示推送的,可以聯(lián)系找我合作哈。(在公眾號(hào)里可以查到我的聯(lián)系方式)

關(guān)于我

我的github主頁(點(diǎn)擊進(jìn)入)

我的掘金主頁(點(diǎn)擊進(jìn)入)

我的簡書主頁(點(diǎn)擊進(jìn)入)

我的公眾號(hào)(點(diǎn)擊進(jìn)入或者掃描下方二維碼)

參考

原生JS實(shí)現(xiàn)最簡單的圖片懶加載

JavaScript高級(jí)程序設(shè)計(jì)

IntersectionObserver API 使用教程

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/53340.html

相關(guān)文章

  • 如何判斷元素是否可視區(qū)域ViewPort

    摘要:在這里一次性做個(gè)總結(jié),以用來判斷元素是否在可視區(qū)域以及用原生簡單實(shí)現(xiàn)懶加載。被隱藏在內(nèi)容區(qū)域左側(cè)的像素?cái)?shù)。比如上篇文章文字跑馬燈項(xiàng)目中的使用戳此跳轉(zhuǎn)小結(jié)只讀屬性,不包括滾動(dòng)條。 個(gè)性簽名: 生如夏花,逝如冬雪;人生如此,何悔何怨。 前言: 經(jīng)常需要計(jì)算元素的大小或者所在頁面的位置,offsetWidth,clientWidth,scrollWidth,scrollTop這幾個(gè)關(guān)鍵字的出...

    jayzou 評(píng)論0 收藏0
  • 如何判斷元素是否可視區(qū)域ViewPort

    摘要:在這里一次性做個(gè)總結(jié),以用來判斷元素是否在可視區(qū)域以及用原生簡單實(shí)現(xiàn)懶加載。被隱藏在內(nèi)容區(qū)域左側(cè)的像素?cái)?shù)。比如上篇文章文字跑馬燈項(xiàng)目中的使用戳此跳轉(zhuǎn)小結(jié)只讀屬性,不包括滾動(dòng)條。 個(gè)性簽名: 生如夏花,逝如冬雪;人生如此,何悔何怨。 前言: 經(jīng)常需要計(jì)算元素的大小或者所在頁面的位置,offsetWidth,clientWidth,scrollWidth,scrollTop這幾個(gè)關(guān)鍵字的出...

    zhigoo 評(píng)論0 收藏0
  • document.elementFromPoint

    摘要:除了坐標(biāo)問題外,該方法只能返回頂層元素,也就是在有個(gè)元素重疊的情況下,只能返回最上層的元素。 先說一下這個(gè)方法的參數(shù) elemntFromPoint(x,y);//傳入坐標(biāo)值,返回當(dāng)前頁面上包含該坐標(biāo)點(diǎn)的頂層元素 注意2點(diǎn),坐標(biāo)值和頂層元素 先說坐標(biāo),因?yàn)椴煌娜死斫馐遣灰粯拥模簿驮炀土诉@個(gè)方法在不同的瀏覽器中表現(xiàn)是不一樣的,所以在傳入坐標(biāo)時(shí)就分 整體頁面坐標(biāo) 和 可視區(qū)域坐標(biāo),我們...

    fredshare 評(píng)論0 收藏0
  • IntersectionObserve初試

    摘要:構(gòu)造函數(shù)調(diào)用時(shí),需要給它傳一個(gè)回調(diào)函數(shù)。當(dāng)監(jiān)聽的元素進(jìn)入可視區(qū)域或者從可視區(qū)域離開時(shí),回調(diào)函數(shù)就會(huì)被調(diào)用。構(gòu)造函數(shù)的返回值是一個(gè)觀察器實(shí)例。它是一個(gè)數(shù)組,每個(gè)成員都是一個(gè)門檻值,默認(rèn)為,即交叉比例達(dá)到時(shí)觸發(fā)回調(diào)函數(shù)。 IntersectionObserve這個(gè)API,可能知道的人并不多(我也是最近才知道...),這個(gè)API可以很方便的監(jiān)聽元素是否進(jìn)入了可視區(qū)域。 * { marg...

    LucasTwilight 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<