整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          WEB圖片批量處理:高效優(yōu)化與加載技巧

          WEB圖片批量處理:高效優(yōu)化與加載技巧

          之前的文章中,我們討論了圖片的尺寸自適應(yīng)、裁切與縮放、壓縮、動(dòng)態(tài)webp等技術(shù)。這些技術(shù)都是對單張圖片的處理,而在實(shí)際項(xiàng)目中,我們往往需要處理大量的圖片。本文將討論如何高效批量優(yōu)化圖片,并介紹一些圖片加載技巧。

          一、圖片預(yù)加載

          圖片預(yù)加載(Preloading Images)是一種提前加載即將使用的圖片資源的技術(shù)。通過在頁面加載時(shí)就將未來可能用到的圖片資源進(jìn)行預(yù)加載,可以在用戶真正需要這些圖片時(shí),減少等待時(shí)間,提升用戶體驗(yàn)。


          HTML中的預(yù)加載


          在HTML中,可以通過<link>標(biāo)簽的rel屬性來實(shí)現(xiàn)圖片預(yù)加載。例如,我們可以在頁面的`<head>`標(biāo)簽中添加如下代碼:

          <link rel="preload" href="image.jpg" as="image" fetchpriority="high">


          <link> 標(biāo)簽用于預(yù)加載一個(gè)圖片資源。讓我們逐個(gè)解釋其中的屬性及其作用:


          • rel="preload":


          當(dāng)前<link>標(biāo)簽的用途是預(yù)加載資源。preload告訴瀏覽器提前加載指定的資源(在這里是圖片),以便在后續(xù)使用時(shí)能夠更快地提供資源。這有助于提高頁面的加載性能,尤其是在資源密集型的網(wǎng)站上。


          • href="image.jpg":


          指定要預(yù)加載的資源的URL。href屬性是一個(gè)URL,指向需要預(yù)加載的資源。在這個(gè)例子中,image.jpg是要預(yù)加載的圖片的路徑。


          • as="image":

          指定預(yù)加載資源的類型。as屬性告訴瀏覽器預(yù)加載資源的類型,以便正確地處理和優(yōu)化加載過程。在這個(gè)例子中,as="image"明確了資源是一個(gè)圖片。這對于瀏覽器優(yōu)化資源加載順序和優(yōu)先級非常重要。


          • fetchpriority="high":


          指定預(yù)加載資源的獲取優(yōu)先級。fetchpriority屬性是一個(gè)新的屬性,用于指示瀏覽器在預(yù)加載資源時(shí)的優(yōu)先級。在這個(gè)例子中,fetchpriority="high"告訴瀏覽器這是一個(gè)高優(yōu)先級的資源,應(yīng)該盡快加載。這在需要確保關(guān)鍵資源(如首屏圖片)快速加載時(shí)非常有用。


          CSS中的預(yù)加載


          在CSS中,可以通過background-image屬性來實(shí)現(xiàn)圖片預(yù)加載。例如,我們可以在CSS文件中添加如下代碼:

          .preload {
           background-image: url('image.jpg');
          }

          這段CSS代碼定義了一個(gè)`.preload`類,其中包含了一個(gè) background-image 屬性,指定了要預(yù)加載的圖片資源的URL。在頁面加載時(shí),瀏覽器會(huì)提前加載這個(gè)圖片資源,以便在后續(xù)使用時(shí)能夠更快地提供資源。


          JavaScript中的預(yù)加載


          JavaScript中,可以通過Image對象來實(shí)現(xiàn)圖片預(yù)加載。例如,我們可以在JavaScript代碼中添加如下代碼:

          var img=new Image();
          img.src='image.jpg';

          這段JavaScript代碼創(chuàng)建了一個(gè)新的Image對象,并設(shè)置了src屬性為要預(yù)加載的圖片資源的URL。當(dāng)這段代碼執(zhí)行時(shí),瀏覽器會(huì)開始加載這個(gè)圖片資源,以便在后續(xù)使用時(shí)能夠更快地提供資源。


          二、圖片懶加載

          圖片懶加載(Lazy Loading Images)是一種延遲加載圖片資源的技術(shù)。通過在頁面加載時(shí)只加載可見區(qū)域內(nèi)的圖片資源,可以減少頁面的加載時(shí)間,提升用戶體驗(yàn)。


          img loading屬性


          HTML中,可以通過loading屬性來實(shí)現(xiàn)圖片懶加載。例如,我們可以在<img>標(biāo)簽中添加如下代碼:


          <img src="image.jpg" loading="lazy" alt="Image">

          loading屬性是一個(gè)新的屬性,用于指定圖片的加載方式。它有三個(gè)可能的值:


          • auto: 默認(rèn)值,表示圖片會(huì)在頁面加載時(shí)立即加載。
          • lazy: 表示圖片會(huì)在視口內(nèi)時(shí)才會(huì)加載。
          • eager: 表示圖片會(huì)在頁面加載時(shí)立即加載,不管是否在視口內(nèi)。


          Intersection Observer API


          JavaScript中,可以通過Intersection Observer API來實(shí)現(xiàn)圖片懶加載。Intersection Observer API是一種用于監(jiān)視元素與視口交叉狀態(tài)的API,可以用于實(shí)現(xiàn)懶加載、無限滾動(dòng)等功能。


          例如,我們可以在JavaScript代碼中添加如下代碼:

          // 創(chuàng)建一個(gè)IntersectionObserver實(shí)例
           const intersectionObserver=new IntersectionObserver((entries)=> {
            entries.forEach(entry=> {
            if (entry.isIntersecting) {
            // 當(dāng)元素與視窗交叉時(shí)執(zhí)行的操作
            const img=entry.target; // entry.target是交叉的元素
            // 假設(shè)data-src屬性包含了圖片的路徑
            img.src=img.dataset.src;
            intersectionObserver.unobserve(img); // 停止觀察該元素
           }
           });
          });
          
          // 為所有需要滾動(dòng)加載的元素(例如圖片)設(shè)置觀察
          document.querySelectorAll('img[data-src]').forEach((img)=> {
           intersectionObserver.observe(img);
          });

          這段JavaScript代碼創(chuàng)建了一個(gè)IntersectionObserver實(shí)例,并為所有帶有data-src屬性的圖片元素設(shè)置了觀察。當(dāng)圖片元素與視口交叉時(shí),會(huì)加載圖片資源,并停止觀察該元素。

          Scroll事件


          JavaScript中,也可以通過監(jiān)聽scroll事件來實(shí)現(xiàn)圖片懶加載。例如,我們可以在JavaScript代碼中添加如下代碼:

          // 獲取所有帶有data-src屬性的圖片元素
           const lazyImages=document.querySelectorAll('img[data-src]');
           // 懶加載函數(shù)
           function lazyLoad() {
            lazyImages.forEach((img)=> {
            if (img.offsetTop < window.innerHeight + window.pageYOffset + 200) {
            img.src=img.dataset.src;
            img.removeAttribute('data-src');
            }
           });
           // 更新 lazyImages,排除已加載的圖片
           lazyImages=document.querySelectorAll('img[data-src]');
           // 如果所有的圖片都已經(jīng)加載,則移除事件監(jiān)聽器
           if (lazyImages.length===0) {
           document.removeEventListener('scroll', lazyLoad);
           }
          }
          // 監(jiān)聽scroll事件
          document.addEventListener('scroll', lazyLoad);
          // 初始檢查一次,以便在頁面加載時(shí)懶加載位于視窗中的圖片
          lazyLoad();

          這段JavaScript代碼監(jiān)聽了scroll事件,并在圖片元素進(jìn)入視口時(shí)加載圖片資源。當(dāng)圖片進(jìn)入視口時(shí),會(huì)加載圖片資源,并移除data-src屬性。


          結(jié)合多種方法來實(shí)現(xiàn)圖片懶加載


          在實(shí)際項(xiàng)目中,我們可以結(jié)合多種方法來實(shí)現(xiàn)圖片懶加載,以便在不同瀏覽器和環(huán)境下提供最佳的用戶體驗(yàn)。例如,我們可以先檢查瀏覽器是否支持loading屬性,如果支持,則使用`loading`屬性實(shí)現(xiàn)圖片懶加載;如果不支持,則檢查瀏覽器是否支持Intersection Observer API,如果支持,則使用Intersection Observer API實(shí)現(xiàn)圖片懶加載;如果不支持,則使用scroll事件實(shí)現(xiàn)圖片懶加載。


          下面是一個(gè)示例代碼,演示了如何結(jié)合多種方法來實(shí)現(xiàn)圖片懶加載:


          html

          <body>
           <img src="placeholder.jpg" data-src="image1.jpg" alt="Description 1">
           <img src="placeholder.jpg" data-src="image2.jpg" alt="Description 2">
           <img src="placeholder.jpg" data-src="image3.jpg" alt="Description 3">
           <!-- 更多 img -->
           <script src="lazyload.js"></script>
          </body>

          javascript

          const lazyImages=document.querySelectorAll('img[data-src]');
          // 判斷瀏覽器是否支持 loading 屬性
          if('loading' in HTMLImageElement.prototype) {
            lazyImages.forEach(img=> {
            img.src=img.dataset.src;
            });
           } else if('IntersectionObserver' in window) {
            // 使用Intersection Observer API實(shí)現(xiàn)懶加載
           const intersectionObserver=new IntersectionObserver((entries)=> {
           entries.forEach(entry=> {
           if (entry.isIntersecting) {
           const img=entry.target;
           img.src=img.dataset.src;
           intersectionObserver.unobserve(img);
           }
           });
           });
          
           lazyImages.forEach((img)=> {
           intersectionObserver.observe(img);
           });
          } else {
           // 使用scroll事件實(shí)現(xiàn)懶加載
           let lazyImages=document.querySelectorAll('img[data-src]');
           function lazyLoad() {
           lazyImages.forEach((img)=> {
           if (img.offsetTop < window.innerHeight + window.pageYOffset + 200) {
           img.src=img.dataset.src;
           img.removeAttribute('data-src');
           }
           });
           lazyImages=document.querySelectorAll('img[data-src]');
           if (lazyImages.length===0) {
           document.removeEventListener('scroll', lazyLoad);
           }
           }
           document.addEventListener('scroll', lazyLoad);
           lazyLoad();
          }

          三、漸進(jìn)式圖片加載

          圖片漸進(jìn)式加載(Progressive Image Loading)是一種逐步加載圖片資源的技術(shù)。通過在圖片加載過程中逐步顯示模糊的低分辨率圖片,可以提升用戶體驗(yàn),減少等待時(shí)間。這種技術(shù)不僅適用于優(yōu)化頁面性能,還可以為用戶提供視覺上的反饋,使頁面顯得更加流暢。


          漸進(jìn)式 JPEG


          漸進(jìn)式 JPEG (Progressive JPEG) 是一種通過逐步顯示圖片的技術(shù),漸進(jìn)式 JPEG 與標(biāo)準(zhǔn)的 JPEG 圖片區(qū)別在于,漸進(jìn)式 JPEG 圖片在加載時(shí)會(huì)逐步顯示圖片的分辨率,而不是一次性顯示完整的圖片。這種逐步加載的方式可以提升用戶體驗(yàn),減少等待時(shí)間。漸進(jìn)式 JPEG 圖片最初會(huì)顯示的是一張模糊的低分辨率圖片,隨著數(shù)據(jù)的不斷加載,圖片的分辨率會(huì)逐步提高,直至達(dá)到全分辨率。這種方法特別適合需要加載大圖的場景。


          許多圖像編輯工具和壓縮工具都支持將圖片保存為漸進(jìn)式 JPEG。在實(shí)際項(xiàng)目中,例如,在 Photoshop 中保存圖片時(shí),可以勾選“漸進(jìn)式”選項(xiàng)。也可以使用命令行工具如ImageMagick(https://imagemagick.org/index.php)來生成漸進(jìn)式 JPEG:

          1convert input.jpg -interlace Plane output.jpg




          需要注意的是漸進(jìn)式 JPEG 圖片的文件大小通常會(huì)比標(biāo)準(zhǔn)的 JPEG 圖片稍大,因?yàn)闈u進(jìn)式 JPEG 圖片包含了更多的數(shù)據(jù),用于逐步顯示圖片的分辨率,但是這種額外的數(shù)據(jù)可以提升用戶體驗(yàn)。因此,在選擇使用漸進(jìn)式 JPEG 圖片時(shí),需要權(quán)衡圖片質(zhì)量和文件大小之間的關(guān)系。


          占位圖技術(shù)


          占位圖技術(shù)(Placeholder Image)通常使用一個(gè)非常小的、模糊的低分辨率圖像作為占位符,在高分辨率圖像加載完成之前先顯示出來。這種方法通過減少初始加載時(shí)間和網(wǎng)絡(luò)請求,可以顯著提升頁面的首屏加載速度。


          占位圖實(shí)現(xiàn)原理很簡單,只需要在頁面中插入一個(gè)占位圖像,然后在高分辨率圖像加載完成后替換為真實(shí)圖像即可。


          • 生成一個(gè)小尺寸的圖片,并將其模糊化處理。
          • 在頁面初始加載時(shí),先顯示這張模糊的小圖,待高分辨率圖像加載完成后再替換。


          代碼示例:

          html:

          <img src="https://fs.autohome.com.cn/energyspace_views/image_demo/compress_before.png?format=webp&dis_rule=20x0_q50_" data-src="https://fs.autohome.com.cn/energyspace_views/image_demo/compress_before.png?format=webp&dis_rule=400x0_q90_" alt="Description">

          javascript:

          document.addEventListener('DOMContentLoaded', function() {
            const lazyImages=document.querySelectorAll('img[data-src]');
            lazyImages.forEach(img=> {
            const placeholder=new Image();
            placeholder.src=img.src;
            placeholder.onload=()=> {
            img.src=img.dataset.src;
            };
            });
          });



          img src 屬性中的圖片是一個(gè)模糊的小圖,data-src 屬性中的圖片是高分辨率圖像。在頁面加載時(shí),先顯示模糊的小圖,待高分辨率圖像加載完成后再替換。


          使用占位圖技術(shù)可以有效減少頁面的加載時(shí)間,提升用戶體驗(yàn)。同時(shí),占位圖技術(shù)也可以結(jié)合圖片懶加載技術(shù)一起使用,進(jìn)一步提升頁面性能。

          四、Base64 編碼

          在 Web 開發(fā)中,將圖片轉(zhuǎn)換為 Base64 編碼是一種優(yōu)化頁面加載速度的方法,但需要權(quán)衡其優(yōu)缺點(diǎn)。一般來說,適用于 Base64 編碼的圖片大小取決于幾個(gè)因素,包括頁面的總體加載時(shí)間、HTTP 請求的數(shù)量以及文件大小。


          Base64 編碼的優(yōu)點(diǎn)


          • 減少 HTTP 請求:將圖像嵌入到 HTML 或 CSS 中可以減少 HTTP 請求,從而加快頁面加載速度。對于小圖標(biāo)或背景圖片,效果尤為顯著。
          • 簡單易用:Base64 編碼圖像是一種文本格式,可以方便地嵌入 HTML、CSS 或 JSON 中,不需要額外的圖像文件管理。
          • 適用于小圖像:Base64 編碼特別適合用于小圖像,例如網(wǎng)站的 logo、按鈕、圖標(biāo)等。


          Base64 編碼的缺點(diǎn)


          • 增加文件體積:Base64 編碼會(huì)使文件體積增加,因此對于大圖像,不推薦使用這種方法。
          • 緩存問題:由于 Base64 圖像嵌入在 HTML 或 CSS 文件中,瀏覽器不能單獨(dú)緩存這些圖像文件,因此在更新圖像時(shí)需要重新下載整個(gè) HTML 或 CSS 文件。
          • 可讀性差:Base64 編碼圖像是一長串字符,嵌入到文檔中會(huì)降低文檔的可讀性和可維護(hù)性。


          適合轉(zhuǎn)為 Base64 的圖片大小一般為 1KB 到 10KB 的圖片:通常,文件大小在 1KB 到 10KB 之間的圖片是轉(zhuǎn)為 Base64 編碼的最佳選擇。這樣的圖片往往是小圖標(biāo)、按鈕、背景圖案等。對于這些小圖片,Base64 編碼可以顯著減少 HTTP 請求的數(shù)量,從而提升頁面加載速度。


          在實(shí)際Web項(xiàng)目開發(fā)中,使用 Webpack Vite 將小圖片自動(dòng)轉(zhuǎn)換為 Base64 編碼是一個(gè)常見的優(yōu)化方法。這種自動(dòng)化的處理可以簡化開發(fā)流程,并確保在構(gòu)建過程中優(yōu)化資源。


          webpack 配置示例:

          module.exports={
            module: {
            rules: [
            {
            test: /\.(png|jpe?g|gif)$/i,
            use: [
            {
            loader: 'url-loader',
            options: {
           limit: 10240, // 10KB
           },
           },
           ],
           },
           ],
           },
          };

          Vite 配置示例:

          import { defineConfig } from 'vite';
          
          export default defineConfig({
           build: {
           assetsInlineLimit: 10240, // 10KB
           },
          });

          在以上配置中,limit assetsInlineLimit 選項(xiàng)指定了圖片轉(zhuǎn)為 Base64 編碼的閾值,超過這個(gè)閾值的圖片將被單獨(dú)打包為文件,而小于這個(gè)閾值的圖片將被轉(zhuǎn)為 Base64 編碼。

          五、結(jié)語

          通過結(jié)合多種圖片加載與優(yōu)化技術(shù),可以提升頁面性能,提供更好的用戶體驗(yàn)。預(yù)加載、懶加載、漸進(jìn)式加載等技術(shù)在不同場景下有著不同的優(yōu)勢,通過合理地選擇和組合這些技術(shù),可以有效地優(yōu)化圖片加載過程。


          在實(shí)際項(xiàng)目中,建議根據(jù)項(xiàng)目的具體需求,選擇合適的技術(shù)和工具進(jìn)行圖片優(yōu)化和加載。希望本文所介紹的技術(shù)和示例代碼能夠幫助您更好地實(shí)現(xiàn)圖片批量處理與加載優(yōu)化,提升網(wǎng)頁的加載速度和用戶體驗(yàn)。


          WEB 圖片優(yōu)化的相關(guān)文章到此結(jié)束,希望對你有所幫助。如果有任何問題或建議,歡迎在評論區(qū)留言,謝謝!



          作者:之家-梁家瑋

          來源-微信公眾號:之家前端共享流

          出處:https://mp.weixin.qq.com/s/bhxtIED32lJP7PY9g28GNA

          網(wǎng)頁設(shè)計(jì)中,添加圖片并為其添加超鏈接是常見的需求。通過使用HTML,我們可以輕松實(shí)現(xiàn)這些功能。下面將詳細(xì)介紹如何實(shí)用地添加圖片,并為圖片添加超鏈接。


          html代碼


          首先,我們需要了解HTML中如何添加圖片。在HTML中,我們使用`<img>`標(biāo)簽來插入圖片。`<img>`標(biāo)簽有幾個(gè)重要的屬性,包括`src`、`alt`和`width`、`height`等。`src`屬性用于指定圖片的URL地址,`alt`屬性用于提供圖片無法加載時(shí)的替代文本,而`width`和`height`屬性則用于設(shè)置圖片的寬度和高度。

          下面是一個(gè)簡單的示例,展示如何在HTML中添加圖片:

          <img src="這里寫圖片地址,要帶http協(xié)議,比如:https://www.chaojilu.com" alt="看不到圖片,就顯示這個(gè)文字" width="500" height="300">

          在這個(gè)示例中,我們使用了`<img>`標(biāo)簽,并通過`src`屬性指定了圖片的URL地址。同時(shí),我們還設(shè)置了`alt`屬性以提供替代文本,并通過`width`和`height`屬性設(shè)置了圖片的尺寸。

          接下來,我們來看如何為圖片添加超鏈接。在HTML中,我們使用`<a>`標(biāo)簽來創(chuàng)建超鏈接。`<a>`標(biāo)簽的`href`屬性用于指定鏈接的目標(biāo)地址。為了將圖片包含在超鏈接中,我們可以將`<img>`標(biāo)簽放置在`<a>`標(biāo)簽內(nèi)部。

          下面是一個(gè)示例,展示如何為圖片添加超鏈接:

          <a href="https://www.chaojilu.com">
          <img src="image.jpg" alt="看不到圖片,就顯示這個(gè)文字"width="這里寫寬度" height="高度">>
          </a>

          在這個(gè)示例中,我們將`<img>`標(biāo)簽放置在`<a>`標(biāo)簽內(nèi)部,并通過`href`屬性指定了鏈接的目標(biāo)地址。當(dāng)用戶點(diǎn)擊圖片時(shí),將會(huì)跳轉(zhuǎn)到指定的網(wǎng)址。同時(shí),我們還通過`alt`屬性為圖片提供了替代文本,以便在圖片無法加載時(shí)為用戶提供提示。

          除了基本的添加圖片和超鏈接功能外,我們還可以通過一些技巧來優(yōu)化圖片的顯示和加載效果。例如,我們可以使用CSS樣式來設(shè)置圖片的邊框、圓角等外觀屬性,提升頁面的美觀度。同時(shí),我們還可以通過壓縮圖片文件大小、使用懶加載等技術(shù)來優(yōu)化圖片的加載速度,提高用戶體驗(yàn)。

          需要注意的是,在添加圖片和超鏈接時(shí),我們需要確保所使用的圖片資源是合法且可訪問的。避免使用未經(jīng)授權(quán)或侵權(quán)的圖片資源,以免引發(fā)法律問題。同時(shí),我們還應(yīng)該關(guān)注圖片的版權(quán)和使用協(xié)議,確保在使用圖片時(shí)遵守相關(guān)規(guī)定。

          總之,通過使用HTML的`<img>`和`<a>`標(biāo)簽,我們可以輕松地在網(wǎng)頁中添加圖片并為圖片添加超鏈接。通過合理設(shè)置屬性和優(yōu)化技巧,我們可以提升圖片的顯示效果和加載速度,為用戶提供更好的瀏覽體驗(yàn)。

          各位鹿友有什么不懂可以在評論區(qū)留言,咱們一起探討學(xué)習(xí)。

          者:麥樂

          來源:恒生LIGHT云社區(qū)

          圖像延遲加載

          想要得到更好的性能體驗(yàn),只靠資源壓縮與恰當(dāng)?shù)奈募袷竭x型,是很難滿足期望的。我們還需要針對資源加載過程進(jìn)行優(yōu)化。

          什么是延遲加載?

          下圖是京東商城的手機(jī)端首頁,當(dāng)元素沒有滑動(dòng)到視線內(nèi)時(shí),圖片src屬性放置了一個(gè)很小的圖片,init_src屬性放置了真正的圖片,只要當(dāng)該元素滑動(dòng)到視線內(nèi)部,才會(huì)將init_src屬性賦值給src去加載真實(shí)的圖片,這就是一個(gè)簡單的圖片延遲加載的過程。

          傳統(tǒng)方式延遲加載

          就是事件監(jiān)聽的方式,通過監(jiān)聽scroll事件與resize事件,并在事件的回調(diào)函數(shù)中去判斷,需要進(jìn)行延遲加載的圖片是否進(jìn)入視窗區(qū)域。

          我們只需要關(guān)注三個(gè)屬性。

          • class屬性,稍后會(huì)在JavaScript中使用類選擇器選取需要延遲加載處理的〈img〉標(biāo)簽。
          • src屬性,加載前的占位符圖片,可用Base64圖片或低分辨率的圖片。
          • data-src屬性,通過該自定義屬性保存圖片真實(shí)的URL外鏈。

          加入頁面中有多張這樣的圖片需要加載。具體的JavaScript實(shí)現(xiàn)邏輯如下,在文檔的DOMContentLoaded事件中,添加延遲加載處理邏輯,首先獲取class屬性名為lazy的所有〈img〉標(biāo)簽,將這些標(biāo)簽暫存在一個(gè)名為lazyImages的數(shù)組中,表示需要進(jìn)行延遲加載但還未加載的圖片集合。當(dāng)一個(gè)圖片被加載后,便將其從lazyImages數(shù)組中移除,直到lazyImages數(shù)組為空時(shí),表示所有待延遲加載的圖片均已經(jīng)加載完成,此時(shí)便可將頁面滾動(dòng)事件移除。

          這里使用了getBoundingClientRect()函數(shù)獲取元素的相對位置.

                  rectObject=object.getBoundingClientRect();
          

          rectObject.top:元素上邊到視窗上邊的距離;

          rectObject.right:元素右邊到視窗左邊的距離;

          rectObject.bottom:元素下邊到視窗上邊的距離;

          rectObject.left:元素左邊到視窗左邊的距離;

          對于只可上下滾動(dòng)的頁面,判斷一個(gè)圖片元素是否出現(xiàn)在屏幕視窗中的方法其實(shí)顯而易見,即當(dāng)元素上邊緣距屏幕視窗頂部的top值小于整個(gè)視窗的高度window.innerHeight時(shí),預(yù)加載的事件處理代碼如下:

          document.addEventListener(DOMContentLoaded, function() {
                const imags=[].slice.call(document.querySelector('.lazy'))
                const active=false; // 限制函數(shù)被頻繁調(diào)動(dòng)
                function load() {
                  if(active===false) {
                    active=true
                    setTimeout(()=> {
                      imags.forEach((img)=> {
                        const objPos=img.getBoundingClientRect();
                        if(objPos.top <=window.innerHeight && objPos.bottom >=0 && img.display !=='done') {
                          img.src=img.dataset.src;
                          img.classList.remove('lazy')
                          imags.filter((i)=> (i !==img))
                          if(imags.length===0) {
                            document.removeEventListener('scroll', load)
                            window.removeEventListener('resize', load)
                            window.removeEventListener('orientationchange', load)
                          }
            
                        }
                      })
                      active=false
                    }, 200)
                  }
          
                }
          
                document.addEventListener('scroll', load)
                window.addEventListener('resize', load)
                window.addEventListener('orientationchange', load)
          
              })
          

          這種方式的有點(diǎn)就是兼容性比較好,缺點(diǎn)是頻繁地進(jìn)行計(jì)算必然會(huì)影響性能,代碼也會(huì)比較繁瑣。

          實(shí)現(xiàn)圖片的延遲加載:Intersection Observer方式

          現(xiàn)代瀏覽器已大多支持了Intersection Observer API,用一句話簡述:每當(dāng)因頁面滾動(dòng)或窗口尺寸發(fā)生變化,使得目標(biāo)元素(target)與設(shè)備視窗或其他指定元素產(chǎn)生交集時(shí),便會(huì)觸發(fā)通過Intersection Observer API配置的回調(diào)函數(shù),在該回調(diào)函數(shù)中進(jìn)行延遲加載的邏輯處理,會(huì)比傳統(tǒng)方式顯得更加簡潔而高效。

          簡單來說,目標(biāo)元素的可見性變化時(shí),就會(huì)調(diào)用觀察器的回調(diào)函數(shù) callback。

          callback一般會(huì)觸發(fā)兩次。一次是目標(biāo)元素剛剛進(jìn)入視口(開始可見),另一次是完全離開視口(開始不可見)。

           document.addEventListener(DOMContentLoaded, function() {
                  const imags=[].slice.call(document.querySelector('.lazy'))
                  if(window.IntersectionObserver && window.IntersectionObserverEntry && window.IntersectionObserverEntry.prototype.intersectionRatio) {
                    var lazyImgObserver=new IntersectionObserver((entries, observer)=> {
                      entries.forEach((entry)=> {
                        if(entry.isIntersecting) {
                          var lazyImg=entry.target;
                          lazyImg.src=lazyImg.dataset.src;
                          lazyImg.classList.remove('lazy');
                          lazyImgObserver.unobserve(lazyImg)
                        }
                      })
                    })
                    imags.forEach((img)=> {
                      lazyImgObserver.observe(img)
                    })
                  }
             
                })
          

          這種方式判斷元素是否出現(xiàn)在視窗中更為簡單直觀,應(yīng)在實(shí)際開發(fā)中盡量使用,但其問題是并非所有瀏覽器都能兼容。

          (1)做好盡量完備瀏覽器兼容性檢查,對于兼容Intersection Observer API的瀏覽器,采用這種方式進(jìn)行處理,而對于不兼容的瀏覽器,則切換回傳統(tǒng)的實(shí)現(xiàn)方式進(jìn)行處理。 (2)使用相應(yīng)兼容的polyfill插件,在W3C官方GitHub賬號下就有提供。

          實(shí)現(xiàn)圖片的延遲加載:CSS類名方式

          這種實(shí)現(xiàn)方式通過CSS的background-image屬性來加載圖片,與判斷〈img〉標(biāo)簽src屬性是否有要請求圖片的URL不同,CSS中圖片加載的行為建立在瀏覽器對文檔分析基礎(chǔ)之上。

            document.addEventListener(DOMContentLoaded, function() {
                  const imags=[].slice.call(document.querySelector('.lazy'))
                  if(window.IntersectionObserver && window.IntersectionObserverEntry && window.IntersectionObserverEntry.prototype.intersectionRatio) {
                    var lazyImgObserver=new IntersectionObserver((entries, observer)=> {
                      entries.forEach((entry)=> {
                        if(entry.isIntersecting) {
                          var lazyImg=entry.target;
                          lazyImg.classList.add('visible');
                          lazyImgObserver.unobserve(lazyImg)
                        }
                      })
                    })
                    imags.forEach((img)=> {
                      lazyImgObserver.observe(img)
                    })
                  }
             
                })
          

          這種方式限制于需要提前寫好css樣式。

          原生的延遲加載支持

          除了上述通過開發(fā)者手動(dòng)實(shí)現(xiàn)延遲加載邏輯的方式,從Chrome 75版本開始,已經(jīng)可以通過〈img〉和〈iframe〉標(biāo)簽的loading屬性原生支持延遲加載了,loading屬性包含以下三種取值。

          ● lazy:進(jìn)行延遲加載。 ● eager:立即加載。 ● auto:瀏覽器自行決定是否進(jìn)行延遲加載。

          測試:image標(biāo)簽就是 img

          <!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>Document</title>
            <!-- <script src="js/file2.js"></script> -->
            <!-- <script src="js/file3.js"></script> -->
            <!-- <link rel="stylesheet" href="css/index.css"> -->
            <style>
              img {
                width: 700px;
                height: 200px;
                display: block;
              }
            </style>
          </head>
          <body>
          
            
            
            <imgage loading="lazy" src='./image/home-1.png' alt="photo" />
            <imgage loading="lazy" src='./image/home-2.png' alt="photo" />
          
            <imgage loading="lazy" src='./image/home-3.png' alt="photo" />
          
            <imgage loading="lazy" src='./image/home-4.png' alt="photo" />
            <imgage loading="lazy" src='./image/home-5.png' alt="photo" />
          
            <imgage loading="lazy" src='./image/home-6.png' alt="photo" />
          
          
            <imgage loading="lazy" src='./image/home-7.png' alt="photo" />
          
            <imgage loading="lazy" src='./image/home-8.png' alt="photo" />
            
            <imgage loading="lazy" src='./image/home-9.png' alt="photo" />
            <imgage loading="lazy" src='./image/home-10.png' alt="photo" />
          
            <imgage loading="lazy" src='./image/home-11.png' alt="photo" />
          
          
            <imgage loading="lazy" src='./image/home-12.png' alt="photo" />
          
            <imgage loading="lazy" src='./image/home-13.png' alt="photo" />
          
            <imgage loading="lazy" src='./image/home-14.png' alt="photo" />
          
            <imgage loading="lazy" src='./image/home-15.png' alt="photo" />
          
          
            <imgage loading="lazy" src='./image/home-16.png' alt="photo" />
          
            <imgage loading="lazy" src='./image/home-17.png' alt="photo" />
            <imgage loading="lazy" src='./image/home-18.png' alt="photo" />
          
            <imgage loading="lazy" src='./image/home-19.png' alt="photo" />
          
            <imgage loading="lazy" src='./image/home-20.png' alt="photo" />
          
          
            <imgage loading="lazy" src='./image/home-21.png' alt="photo" />
          
            <imgage loading="lazy" src='./image/home-22.png' alt="photo" />
            
            <imgage loading="lazy" src='./image/home-23.png' alt="photo" />
          
            <imgage loading="lazy" src='./image/home-24.png' alt="photo" />
          
          
            <imgage loading="lazy" src='./image/home-25.png' alt="photo" />
          
            <imgage loading="lazy" src='./image/home-26.png' alt="photo" />
            <imgage loading="lazy" src='./image/home-27.png' alt="photo" />
          
            <imgage loading="lazy" src='./image/home-28.png' alt="photo" />
          
          
            <imgage loading="lazy" src='./image/home-29.png' alt="photo" />
          
          <imgage loading="lazy" src='./image/home-30.png' alt="photo" />
          
          
          
          </body>
          </html>
          

          可以看到,首次加載的個(gè)數(shù)是13個(gè),首屏一般只能放下4個(gè)左右,13個(gè)以后的img滾動(dòng)到視線內(nèi)部會(huì)自動(dòng)去加載。

          實(shí)踐發(fā)現(xiàn)有以下幾個(gè)特點(diǎn):

          1. Lazy loading加載數(shù)量與屏幕高度有關(guān),高度越小加載數(shù)量越少,但并不是線性關(guān)系。
          2. Lazy loading加載數(shù)量與網(wǎng)速有關(guān),網(wǎng)速越慢,加載數(shù)量越多,但并不是線性關(guān)系。
          3. Lazy loading加載沒有緩沖,滾動(dòng)即會(huì)觸發(fā)新的圖片資源加載。
          4. Lazy loading加載在窗口resize尺寸變化時(shí)候也會(huì)觸發(fā),例如屏幕高度從小變大的時(shí)候。
          5. Lazy loading加載也有可能會(huì)先加載后面的圖片資源,例如頁面加載時(shí)滾動(dòng)高度很高的時(shí)候。

          與JavaScript有關(guān)的幾個(gè)行為特征:

          1. 判斷瀏覽器是否支持原生loading,最好使用'loading' in XXX判斷。
          2. 獲取loading屬性值可以直接img.loading;
          3. 原生loading不可寫,不可訪問例如HTMLImageElement.prototype.loading會(huì)報(bào)錯(cuò)Illegal invocation。
          4. 如果要使用,注意做兼容性處理。

          主站蜘蛛池模板: 日韩一区二区在线观看| 成人h动漫精品一区二区无码| 亚洲一区二区三区四区视频 | 国产内射999视频一区| 亚洲AV无码一区东京热久久 | 亚洲视频在线一区二区| 一区视频在线播放| 男女久久久国产一区二区三区| 国产精品一区在线观看你懂的| 成人精品一区二区三区电影| 国产在线不卡一区二区三区| 亚洲日韩中文字幕一区| 国产免费无码一区二区| 日韩久久精品一区二区三区| 久久人做人爽一区二区三区| 精品日韩在线视频一区二区三区| 在线精品视频一区二区| 人妻激情偷乱视频一区二区三区| 亚洲第一区精品日韩在线播放| 无码人妻一区二区三区免费| 日韩亚洲AV无码一区二区不卡 | 亚洲综合一区二区精品导航| 国产韩国精品一区二区三区| 国产一区二区三区精品久久呦| 亚洲综合一区二区| 国产精品自拍一区| 麻豆一区二区免费播放网站| 亚洲一区二区三区国产精品无码 | 亚洲a∨无码一区二区| 伊人色综合视频一区二区三区| 无码av免费毛片一区二区| 中文字幕一区一区三区| 成人区精品一区二区不卡亚洲| 日韩中文字幕一区| 免费萌白酱国产一区二区| 国产丝袜一区二区三区在线观看 | 国产精品va无码一区二区| 日本伊人精品一区二区三区| 无码中文人妻在线一区| 久久一区二区三区精华液使用方法 | 国产伦精品一区二区|