圖片幾種懶加載方式

故問題拆分成兩個:

  1. 如何判斷圖片出現在了當前視口 (即如何判斷我們能夠看到圖片)
  2. 如何控制圖片的加載

如何判斷圖片出現在了當前視口

clientTopoffsetTopclientHeight 以及scrollTop各種關于圖片的高度作比對

這些高度都代表了什么意思?
HTML精確定位:scrollLeft,scrollWidth,clientWidth,offsetWidth

  • scrollHeight: 獲取對象的滾動高度。
  • scrollLeft:設置或獲取位于對象左邊界和窗口中目前可見內容的最左端之間的距離
  • scrollTop:設置或獲取位于對象最頂端和窗口中可見內容的最頂端之間的距離
  • scrollWidth:獲取對象的滾動寬度
  • offsetHeight:獲取對象相對于版面或由父坐標offsetParent屬性指定的父坐標的高度
  • offsetLeft:獲取對象相對于版面或由 offsetParent屬性指定的父坐標的計算左側位置
  • offsetTop:獲取對象相對于版面或由 offsetTop屬性指定的父坐標的計算頂端位置
  • event.clientX 相對文檔的水平座標
  • event.clientY相對文檔的垂直座標
  • event.offsetX 相對容器的水平坐標
  • event.offsetY 相對容器的垂直坐標
  • document.documentElement.scrollTop 垂直方向滾動的值
  • event.clientX+document.documentElement.scrollTop 相對文檔的水平座標+垂直方向滾動的量

這里是javascript中建造遷移轉變代碼的常用屬性

  • 網頁可見區域寬: document.body.clientWidth;
  • 網頁可見區域高: document.body.clientHeight;
  • 網頁可見區域寬: document.body.offsetWidth (包含邊線的寬);
  • 網頁可見區域高: document.body.offsetHeight (包含邊線的寬);
  • 網頁正文全文寬: document.body.scrollWidth;
  • 網頁正文全文高: document.body.scrollHeight;
  • 網頁被卷去的高: document.body.scrollTop;
  • 網頁被卷去的左: document.body.scrollLeft;
  • 網頁正文項目組上: window.screenTop;
  • 網頁正文項目組左: window.screenLeft;
  • 屏幕辨別率的高: window.screen.height;
  • 屏幕辨別率的寬:window.screen.width;
  • 屏幕可用工作區高度: window.screen.availHeight;

僅僅知道它靜態的高度還不夠,我們還需要知道動態的

如何動態?監聽window.scroll事件

如何控制圖片的加載

<img data-src="JimiLee.jpg">

首先設置一個臨時屬性 data-src,控制加載時使用 src 代替 data-src

改進下,如何判斷圖片出現在了當前視口

引入一個新的 API, Element.getBoundingClientRect()方法返回元素的大小及其相對于視口的位置。
https://mdn.mozillademos.org/files/15087/rect.png

image

那如何判斷圖片出現在了當前視口呢,根據示例圖示意,代碼如下,這個就比較好理解了,就可以很容易地背會

// clientHeight 代表當前視口的高度
img.getBoundingClientRect().top < document.documentElement.clientHeight

監聽 window.scroll 事件也優化一下

加個節流器,提高性能。工作中一般使用 lodash.throttle 就可以了

_.throttle(func, [wait=0], [options={}])

如何判斷圖片出現在了當前視口

方案二使用的方法是: window.scroll 監聽 Element.getBoundingClientRect() 并使用 _.throttle 節流

一系列組合動作太復雜了,于是瀏覽器出了一個三合一事件: IntersectionObserver API,一個能夠監聽元素是否到了當前視口的事件,一步到位!

事件回調的參數是IntersectionObserverEntry 的集合,代表關于是否在可見視口的一系列值

其中,entry.isIntersecting 代表目標元素可見

const observer = new IntersectionObserver((changes) => {
  // changes: 目標元素集合
  changes.forEach((change) => {
    // intersectionRatio
    if (change.isIntersecting) {
      const img = change.target
      img.src = img.dataset.src
      observer.unobserve(img)
    }
  })
})

observer.observe(img)

當然,IntersectionObserver 除了給圖片做懶加載外,還可以對單頁應用資源做預加載。

總結一下

  • window.scroll 監聽各種 topheight 并使用_.throttle 節流,但是不好理解各種 tophegith
  • window.scroll監聽 getBoundingClientRect 并使用_.throttle 節流,沒有一個統一事件,相對復雜
  • IntersectionObserver,瀏覽器推出了一個事件,方便簡單
  • img.loading=lazy,瀏覽器直接給你解決,開發者直接標注屬性
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。