現代圖片性能優化及體驗優化指南 - 響應式圖片方案

来源:https://www.cnblogs.com/coco1s/archive/2023/02/21/17139699.html
-Advertisement-
Play Games

本文是系列第二篇。系列文章: 現代圖片性能優化及體驗優化指南 - 圖片類型及 Picture 標簽的使用 圖片資源,在我們的業務中可謂是占據了非常大頭的一環,尤其是其對帶寬的消耗是十分巨大的。 對圖片的性能優化及體驗優化在今天就顯得尤為重要。本文,就將從各個方面闡述,在各種新特性滿頭飛的今天,我們可 ...


本文是系列第二篇。系列文章:

  1. 現代圖片性能優化及體驗優化指南 - 圖片類型及 Picture 標簽的使用

圖片資源,在我們的業務中可謂是占據了非常大頭的一環,尤其是其對帶寬的消耗是十分巨大的。

對圖片的性能優化及體驗優化在今天就顯得尤為重要。本文,就將從各個方面闡述,在各種新特性滿頭飛的今天,我們可以如何儘可能的對我們的圖片資源,進行性能優化及體驗優化。

適配不同的屏幕尺寸及 DPR

下一個模塊,我們來看看圖片資源如何更好的適配不同的屏幕尺寸。

這裡首先會涉及一個預備知識,屏幕的 DPR 值,那麼,什麼是 DPR 呢?要瞭解 DPR,又需要知道什麼是設備獨立像素 以及 物理像素

設備獨立像素

以 iPhone6/7/8為例,這裡我們打開 Chrome 開發者工具:

這裡的 375 * 667 表示的是什麼呢,表示的是設備獨立像素(DIP),也可以理解為 CSS 像素,也稱為邏輯像素:

設備獨立像素 = CSS 像素 = 邏輯像素

如何記憶呢?這裡使用 CSS 像素來記憶,也就是說。我們設定一個寬度為 375px 的 div,剛好可以充滿這個設備的一行,配合高度 667px ,則 div 的大小剛好可以充滿整個屏幕。

物理像素

OK,那麼,什麼又是物理像素呢。我們到電商網站購買手機,都會看一看手機的參數,以 JD 上的 iPhone7 為例:

可以看到,iPhone7 的解析度是 1334 x 750,這裡描述的就是屏幕實際的物理像素。

物理像素,又稱為設備像素。顯示屏是由一個個物理像素點組成的,1334 x 750 表示手機分別在垂直和水平上所具有的像素點數。通過控制每個像素點的顏色,就可以使屏幕顯示出不同的圖像,屏幕從工廠出來那天起,它上面的物理像素點就固定不變了,單位為pt。

設備像素 = 物理像素

DPR(Device Pixel Ratio) 設備像素比

OK,有了上面兩個概念,就可以順理成章引出下一個概念。DPR(Device Pixel Ratio) 設備像素比,這個與我們通常說的視網膜屏(多倍屏,Retina屏)有關。

設備像素比描述的是未縮放狀態下,物理像素和設備獨立像素的初始比例關係。

簡單的計算公式:

DPR = 物理像素 / 設備獨立像素

我們套用一下上面 iPhone7 的數據(取設備的物理像素寬度與設備獨立像素寬度進行計算):

iPhone7’s DPR = iPhone7’s 物理像素寬度 / iPhone7's 設備獨立像素寬度 = 2

750 / 375 = 2
或者是 1334 / 667 = 2

可以得到 iPhone7 的 dpr 為 2。也就是我們常說的視網膜屏幕。

視網膜(Retina)屏幕是蘋果公司"發明"的一個營銷術語。 蘋果公司將 dpr > 1 的屏幕稱為視網膜屏幕。

在視網膜屏幕中,以 dpr = 2 為例,把 4(2x2) 個像素當 1 個像素使用,這樣讓屏幕看起來更精緻,但是元素的大小本身卻不會改變:

OK,我們再來看看 iPhone XS Max:

它的物理像素如上圖是 2688 x 1242

它的 CSS 像素是 896 x 414,很容易得出 iPhone XS Max 的 dpr 為 3。

為不同 DPR 屏幕,提供恰當的圖片

那麼,DPR 和圖片適配有什麼關係呢?

舉個例子,同樣的 CSS 像素大小下,屏幕如果有不同 DPR,同樣大小的圖片渲染出來的效果不盡相同。

我們以 dpr = 3 的手機為例子,在 300 x 389 CSS 像素大小的範圍內,渲染 1倍/2倍/3倍 圖的效果如下:

實際圖片所占的物理像素為 900 x 1167。

可以看到,在高 DPR 設備下提供只有 CSS 像素大小的圖片,是非常模糊的。

因此,為了在不同的 DPR 屏幕下,讓圖片看起來都不失真,我們需要為不同 DPR 的圖片,提供不同大小的圖片。

那麼,有哪些可行的解決方案呢?

方案一:無腦多倍圖

假設,在移動端假設我們需要一張 CSS 像素為 300 x 200 的圖像,考慮到現在已經有了 dpr = 3 的設備,那麼要保證圖片在 dpr = 3 的設備下也正常高清展示,我們最大可能需要一張 900 x 600 的原圖。

這樣,不管設備的 dpr 是否為 3,我們統一都使用 3 倍圖。這樣即使在 dpr = 1,dpr = 2 的設備上,也能非常好的展示圖片。

當然這樣並不可取,會造成大量帶寬的浪費。

現代瀏覽器,提供了更好的方式,讓我們能夠根據設備 dpr 的不同,提供不同尺寸的圖片。

方案二:媒體查詢

方案二,我們可以考慮使用媒體查詢。到今天,我們可以通過相應的媒體查詢,得知當前的設備的 DPR 值,這樣,我們就可以在對應的媒體查詢中,使用對應的圖片。

像是這樣:

#id { 
    background: url([email protected]) 
}
@media (device-pixel-ratio: 2) {
    #id { 
        background: url([email protected]) 
    }
}
@media (device-pixel-ratio: 3) {
    #id { 
        background: url([email protected]) 
    }
}

這個方案的缺點在於:

  1. 要寫的代碼可能太多了,而且,可能存在一些介於 12,23 之間的 DPR 值,不好窮舉出所有場景
  2. 需要註意語法需要的相容性,需要添加首碼,譬如 -webkit-min-device-pixel-ratio,當然這個可以由 autoprefixer 輔助解決

方案三:CSS 配合 image-set 語法

image-set 屬於 CSS background 中的一種語法,image-set() 函數為設備提供最合適的圖像解析度,它提供一組圖像選項,每個選項都有一個相關的 DPR 聲明,瀏覽器將從中選擇最適合設備的圖像進行設置。

什麼意思呢,來看看代碼:

.img {
    /* 不支持 image-set 的瀏覽器*/
    background-image: url('../[email protected]');

    /* 支持 image-set 的瀏覽器*/
    background-image: image-set(
        url('./[email protected]') 2x,
        url('./[email protected]') 3x
    );
}

這樣一看,作用應該很清晰了。對於支持 image-set 語法的瀏覽器:

  1. 如果其設備對應的 DPR 為 2,會選取這條 url('./[email protected]') 2x 記錄,也就是最終生效的 URL 是 './[email protected]'
  2. 如果其設備對應的 DPR 為 3,會選取這條 url('./[email protected]') 3x 記錄,也就是最終生效的 URL 是 './[email protected]'

其中的 2x3x 就是用於匹配 DRP的。

使用 image-set 的一些痛點與媒體查詢方案類似。代碼量與相容性語法,而且難以匹配所有情況。

方案四:srcset 配合 1x 2x 像素密度描述符

簡單來說,srcset 可以根據不同的 dpr 拉取對應尺寸的圖片:

<div class='illustration'>
   <img src='illustration-small.png'
       srcset='images/illustration-small.png 1x,
               images/illustration-big.png 2x'
   >
</div>

上面 srcset 里的 1x,2x 表示 像素密度描述符,表示

  • 當屏幕的 dpr = 1 時,使用 images/illustration-small.png 這張圖
  • 當屏幕的 dpr = 2 時,使用 images/illustration-big.png 這張圖
  • 如果不支持 srcset 語法,src='illustration-small.png' 將會是最終的兜底方案

方案五:srcset 屬性配合 sizes 屬性 w 寬度描述符

上面 1x,2x 的寫法比較容易接受易於理解。

但是,上述 3 種方案都存在統一的問題,只考慮了 DPR,但是忽略了響應性佈局的複雜性與屏幕的多樣性

因此,規範還推出了一種方案 -- srcset 屬性配合 sizes 屬性 w 寬度描述符

srcset 屬性還有一個 w 寬度描述符,配合 sizes 屬性一起使用,可以覆蓋更多的面。

sizes 屬性怎麼理解呢?它定義圖像元素在不同的視口寬度時,可能的大小值。

以下麵這段代碼為例子:

<img 
        sizes = “(min-width: 600px) 600px, 300px" 
        src = "photo.png" 
        srcset = “[email protected] 300w,
                       [email protected] 600w,
                       [email protected] 1200w,
>

解析一下:

sizes = “(min-width: 600px) 600px, 300px" 的意思是:

  1. 如果屏幕當前的 CSS 像素寬度大於或者等於 600px,則圖片的 CSS 寬度為 600px
  2. 反之,則圖片的 CSS 寬度為 300px

也就是 sizes 屬性聲明瞭在不同寬度下圖片的 CSS 寬度表現。這裡可以理解為,大屏幕下圖片寬度為 600px,小屏幕下圖片寬度為 300px。

需要註意的是,這裡大屏、小屏下圖片具體的寬度表現,還是需要藉助媒體查詢代碼,經由 CSS 實現的

srcset = “[email protected] 300w, [email protected] 600w, [email protected] 1200w 裡面的 300w,600w,900w 叫寬度描述符。

那麼,怎麼確定當前場景會選取哪張圖片呢?

當前屏幕 dpr = 2 ,CSS 寬度為 375px

當前屏幕 CSS 寬度為 375px,則圖片 CSS 寬度為 300px。分別用上述 3 個寬度描述符的數值除以 300。

  1. 300 / 300 = 1
  2. 600 / 300 = 2
  3. 1200 / 300 = 4

上面計算得到的 1、 2、 4 即是算出的有效的像素密度,換算成和 x 描述符等價的值 。這裡 600w 算出的 2 即滿足 dpr = 2 的情況,選擇此張圖。

當前屏幕 dpr = 3 ,CSS 寬度為 414px

當前屏幕 CSS 寬度為 414px,則圖片 CSS 寬度仍為 300px。再計算一次:

  1. 300 / 300 = 1
  2. 600 / 300 = 2
  3. 1200 / 300 = 4

因為 dpr = 3,2 已經不滿足了,則此時會選擇 1200w 這張圖。

當前屏幕 dpr = 1 ,CSS 寬度為 1920px

當前屏幕 CSS 寬度為 1920px,則圖片 CSS 寬度變為了 600px。再計算一次:

  1. 300 / 600 = .5
  2. 600 / 600 = 1
  3. 1200 / 600 = 2

因為 dpr = 1,所以此時會選擇 600w 對應的圖片。

具體的可以試下這個 Demo:CodePen Demo -- srcset屬性配合w寬度描述符配合sizes屬性

此方案的意義在於考慮到了響應性佈局的複雜性與屏幕的多樣性,利用上述規則,可以一次適配 PC 端大屏幕和移動端高清屏,一箭多雕。

嗯,總結一下,在實現響應式圖像時,我們同時使用 srcsetsizes 屬性。它們的作用是:

  • srcset:定義多個不同寬度的圖像源,讓瀏覽器在 HTML 解析期間選擇最合適的圖像源
  • sizes:定義圖像元素在不同的視口寬度時,可能的大小值

有了這些屬性後,瀏覽器就會根據 srcset/size 來創建一個解析度切換器的響應式圖片,可以在不同的解析度的情況下,提供相同尺寸的圖像,或者在不同的視圖大小的情況下,提供不同尺寸大小的圖像。

本章總結

本章節一共列舉了 5 種實現響應式圖片,適配不同屏幕大小,不同 DPR 的方式,它們分別是:

  1. 無腦多倍圖的方式
  2. DRP 媒體查詢
  3. CSS Background 中的使用 image-set
  4. srcset 配合 1x 2x 像素密度描述符
  5. srcset 屬性配合 sizes 屬性 w 寬度描述符

合理使用它們,可以有效的為不同屏幕,提供最為恰當的圖片資源,在保證用戶體驗的同時,儘可能節省帶寬。

它們各有優缺點,可以根據自己實際的業務場景,選取合適相對成本最低的方案,並且適當的配合 Autoprefixer 以及一些 PostCSS 等工具,簡化代碼量。

當然,本文只是現代圖片性能優化及體驗優化指南的第二篇,後續將給大家帶來圖片在:

  • 圖片的寬高比、裁剪與縮放展示
  • 懶載入/非同步圖像解碼方案
  • 可訪問性以及圖片資源的容錯及錯誤處理

等相關知識的介紹,感興趣的可以提前關註。

最後

OK,本文到此結束,希望本文對你有所幫助

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 最近公司出了一個新的功能模塊(如下圖),大提上可以描述為實現拍照完上傳圖片,拖動四方框拍照完成上傳功能,大體樣子如下圖。但是我找遍了 dcloud 插件市場,找到的插件都是移動背景圖片來實現裁剪的,跟京東的功能是相反的,沒辦法只能自己來實 ...
  • 前言 在 JavaScript 中,對象是一種非常常見的數據類型,幾乎每個程式員都會在日常工作中頻繁地使用對象。在本篇文章中,我們將深入瞭解 JavaScript 對象的一些基本概念和一些高級概念,這些概念對於我們正確理解對象在 JavaScript 中的行為非常重要。 對象的基本概念 在 Java ...
  • 前面使用了 11 篇文章分享基於 vue3 、Monorepo 的組件庫工程完整四件套(組件庫、文檔、example、cli)的開發、構建及組件庫的發佈。本文屬於這 11 篇文章的擴展 —— 如何發佈到 GitHub 上以及如何快速利用 GitHub 發佈組件庫文檔。這樣優雅哥的《組件庫框架》系列便 ...
  • 第一步:在gitee新建一個倉庫 寫上基本信息,點擊創建(不要勾選初始化),記住項目名稱 成功後的頁面中,把這個項目地址複製好 第二步VS code推送至gitee 把項目地址粘貼在輸入框,回車 再輸入剛纔新建的項目名稱,回車 此時第一次提交會有新彈窗界面,提示輸入gitee的用戶名和密碼,輸入後點 ...
  • 字元串 substring 形式:substring(index1, index2) 不會改變原始字元串 將小的參數作為開始位置 start,大的作為結束位置 stop 包含 start,但不包含 stop 如果只給一個參數表示從它 start 截取到字元串結尾 如果某個參數為負,會先將負數變為 0 ...
  • 二進位和八進位表示法 ES6提供了二進位和八進位數值的新的寫法,分別用首碼0b(或0B)和0o或(0O)表示 0b111110111 503 // true; 0o767 503; // true 在es5開始,嚴格模式中,八進位不允許使用首碼0 表示,否則會報錯 // 嚴格模式 (function ...
  • 代碼組織 代碼按一下順序組織: @import 變數聲明 樣式聲明 1 @import "mixins/size.less"; 2 @default-text-color: #333; 3 .page { 4 width: 960px; 5 margin: 0 auto; 6 } @import 語 ...
  • vue2 使用 cesium 篇 今天好好寫一篇哈,之前寫的半死不活的。首先說明:這篇博文是我邊做邊寫的,小白也是,實現效果會同時發佈截圖,如果沒有實現也會說明,僅僅作為技術積累,選擇性分享,不做教學哈。不好別噴。 安裝 cesium 這個就很簡單,只需要一句簡簡單單的命令就可以實現在 vue 項目 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...