[盤點] 專案中可以怎麼優化圖片

守候i發表於2018-11-26

看似平常的事物,往往會蘊含的巨大的智慧。把看似平常的事物簡單做好,可能很正常。如果能把平常的事物做精,做細,這個不平常。

1.前言

每一個開發者在開發專案中,不可避免要和圖片打交道,優化圖片似乎也成了一個必修課。圖片優化也不僅僅是效能上的優化,還要進行體驗上的優化。至於怎麼優化圖片,沒有固定的方式,只能具體場景,具體分析,選擇合適的方案。不多說,下面也簡單介紹下自己處理過,瞭解過的一些方式。如果大家有補充,建議。歡迎在評論區留言,交流學習下。

2.概念用法

‘概念用法’ 這個詞是自己亂起的,可能不太準確,是因為詞窮了,不知道怎樣形容。總得來說,這部分介紹的處理方式,就是講一下就知道怎麼用的方式,不需要怎麼放程式碼,執行圖等。只需要籠統的介紹一下,大家都會懂的一些方式。

2-1.圖片壓縮

這個沒有隱含的意思,就是把圖片的大小進行壓縮。目前自己用的比較多的兩個壓縮網站是TinyPng智圖。使用比較方便,品質也基本保持一致。

2-2.base64代替小圖示

一些比較小的圖示,使用 base64 編碼代替可以減少 http 請求。但是有一個缺點就是轉成 base64 後,編碼會比原圖更大,圖片越大,差別就越大。1K左右的圖示,轉碼出來的 base64 大概是 1.1K-2K。如果是 8K 的圖片,轉碼出來的 base64 可能超過10K。就自己專案開發而言,只有小於 4K 的圖示,才會進行轉碼。

2-3.icon-font代替圖示

由於 icon-font 看著是圖片,實際上是字型。

優點:就是在於可以向量縮放,大小圖示都可以使用,也可以改變顏色,使用也不麻煩。

缺點:需要引入的檔案不少(.svg,.ttf,.woff,.eot )。檔案大小也比較大。建議是專案的圖示要達到一定量才使用 icon-font,如果是幾個圖示,還是用圖片吧。如果需要引入的圖示多,就建議使用 icon-font。

上面說的 icon-font 由於是字型,所以不支援多色圖示。有了解到,現在 icon-font 可以支援多色圖示了(symbol引用)。只是相容性不好。

2-4.雪碧圖

雪碧圖就是把很多小的圖整合到一起,製作成一張比較大的圖,然後作為元素的背景圖片使用,定位到相應的圖片即可。

優點:減少了大量的 http 請求。

缺點:背景定位和在移動端適配大小有點麻煩。

除此之外,使用雪碧圖,有兩個個注意地方

1.不要把頁面所有的圖片都合併,比如把 logo 整合會破壞 html 的語義結構。影象複雜的 banner 也不要合併

2.儘量只把顏色相近的圖示整合在一張圖片上,如果圖片顏色相差太大,合併出來的圖片可能會很大。

2-5.響應式圖片

比如頁面上有一張尺寸是 100*100 的圖片,但是圖片的實際尺寸是 1000*1000 的。這樣的情況建議在多準備一張 100*100 的圖片。不然可能會造成資源浪費。

2-6.混合模式代替變色的圖示

如下例子,比如頁面有這個圖示

[盤點] 專案中可以怎麼優化圖片

在特定情況下會是下面這個顏色。

[盤點] 專案中可以怎麼優化圖片

同一個圖示,在不同的時候是不同的顏色。icon-font 可以通過改變 color 實現。或者用兩張圖片。除了這兩個方法,用 CSS3 的混合模式,一樣可以實現。兩行程式碼搞定。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			div{
			    /*容器必須有背景*/
    			    background: #09f;
    			    display: inline-block;
			}
			img{
			    width: 100px;
			    vertical-align: top;
			}
			img:hover{
			    /*設定混合模式*/
			    mix-blend-mode: lighten;
			}
		</style>
	</head>
	<body>
		<div><img src="images/icon-good.jpg" class="u-icon"/></div>
		<div><img src="images/icon-good.png" class="u-icon"/></div>
	</body>
</html>
複製程式碼

執行效果

[盤點] 專案中可以怎麼優化圖片

展示完 mix-blend-mode,順便提下 background-blend-mode 。用法基本一致,只是 mix-blend-mode 作用於 html 元素的混合模式,background-blend-mode 作用於元素背景的混合模式。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			div{
				display: inline-block;
				width: 100px;
				height: 100px;
				/*設定背景*/
				background: url(images/icon-good.jpg) no-repeat center,#09f;
				background-size:100%;
				/*設定背景混合模式*/
				background-blend-mode: lighten;
			}
			
		</style>
	</head>
	<body>
		<div></div>
	</body>
</html>
複製程式碼

[盤點] 專案中可以怎麼優化圖片

注意事項

1.圖片必須是白底純色圖示

2.現代的瀏覽器,支援這個屬性的瀏覽器

如果圖片是透明純色背景,得到的結果會是這樣

[盤點] 專案中可以怎麼優化圖片

受限篇幅影響,混合模式暫時就介紹這麼多,以後發現好玩的再寫文章。有興趣可以看下面的參考資料。

兩行 CSS 程式碼實現圖片任意顏色賦色技術

不可思議的顏色混合模式 mix-blend-mode

不可思議的混合模式 background-blend-mode

2-7.簡單圖示使用 CSS 畫

有一些簡單的圖示,可以使用 CSS 代替。比如下面這些

自己而言,專案上畫的最多的就是各種箭頭

[盤點] 專案中可以怎麼優化圖片

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			.icon-arrow-bottom { 
				width: 0; 
				height: 0; 
				border: 100px solid #000; 
				border-color: #000 transparent transparent transparent; 
			}
			.icon-arrow-top { 
				width: 0; 
				height: 0; 
				border: 100px solid #000; 
				border-color: transparent transparent #000 transparent; 
			}
		</style>
	</head>
	<body>
		<div class="icon-arrow-bottom"></div>
		<div class="icon-arrow-top"</div>
	</body>
</html>
複製程式碼

優點:向量縮放,顏色可變,不需要傳送請求

缺點:只適合用簡單圖形,1-5行 CSS 程式碼可以搞定的才建議用,超過的不建議。想得痛苦,寫也麻煩,花時間也多,效果未必比其它方案好。建議還是圖片 base64,或者 icon-font。

這裡就簡單舉個例子,需要知道 css3 還可以畫什麼圖形。看參考資料。

純CSS製作的圖形效果

奇妙的 CSS shapes(CSS圖形)

【CSS】用CSS繪製圖示(圖示大全)

3.隱式預載入

1.從這裡開始。下面的demo,有些會用到 ecDo 這個庫(自己寫的一個常用函式庫,歡迎star)。之前的文章有介紹過,這裡就不再重複。大家不知道的時候點開看下相應的 API ,執行下,除錯下就好。

2.為方便展示,下面的demo,除了懶載入,都有在 network 把網速調至了慢速的3G。

有些專案圖片比較多,如果一次性載入,使用者等待時間會過久,可能會造成體驗效果很差,甚至導致使用者流失,很多網站用到的一個體驗優化方式是隱式預載入。

等待首屏載入,在使用者看首屏(第一張大圖)的時候,悄悄的載入其它圖片(這裡為了展示效果,在專案上其他的小圖片不應在第一屏)。

[盤點] 專案中可以怎麼優化圖片

<body>
    <p><img src="lawyerOtherImg.jpg"/></p>
    <p>這是預載入的圖片</p>
    <div>
        <img data-src="https://materialdb.zhaoyl.com/201809/106796.jpg" class="load-img" width="100" height="100"/><img
            data-src="https://materialdb.zhaoyl.com/201809/105567.jpg" class="load-img" width="100" height="100"/><img
            data-src="https://materialdb.zhaoyl.com/201809/103097.jpg" class="load-img" width="100" height="100"/><img
            data-src="https://materialdb.zhaoyl.com/201809/10205.jpg" class="load-img" width="100" height="100"/><img
            data-src="https://materialdb.zhaoyl.com/201809/001.jpg" class="load-img" width="100" height="100"/>
    </div>
</body>
複製程式碼
//測試請先清空快取
window.onload = function () {
    ecDo.loadImg('load-img', function () {
        console.log('載入完畢')
    });
}
複製程式碼

注意事項:

1.大概預測,使用者看首屏的時候,很大概率會往下面看。

2.該方式,使用者等待的時間比較短。但是圖片超大,要慎重考慮。因為該方式無法保證使用者在瀏覽的時候,能把下一屏(比如瀏覽第一屏的時候,要載入第二屏)的圖片載入完畢,讓使用者無感知。如果切換的下一屏還沒載入完畢,也可能會影響體驗。

demo:github.com/chenhuiYj/e…

4.顯式預載入

告訴使用者正在載入,等到載入完了再一次性渲染在頁面上。

[盤點] 專案中可以怎麼優化圖片

<style>
    div{
        display: none;
    }
</style>
<body>
    <p id="p">顯示預載入進行中</p>
    <div id="div">
        <img data-src="https://materialdb.zhaoyl.com/201809/106796.jpg" class="load-img" width="100" height="100"/><img
            data-src="https://materialdb.zhaoyl.com/201809/105567.jpg" class="load-img" width="100" height="100"/><img
            data-src="https://materialdb.zhaoyl.com/201809/103097.jpg" class="load-img" width="100" height="100"/><img
            data-src="https://materialdb.zhaoyl.com/201809/10205.jpg" class="load-img" width="100" height="100"/><img
            data-src="https://materialdb.zhaoyl.com/201809/001.jpg" class="load-img" width="100" height="100"/>
    </div>
</body>
複製程式碼
let oP1=document.getElementById('p');
let oDiv=document.getElementById('div');
//測試請先清空快取
window.onload = function () {
    ecDo.loadImg('load-img', function () {
        oDiv.style.display='block';
        oP1.style.display='none';
    });
}
複製程式碼

注意事項:

1.大概預測,使用者看首屏的時候,很大概率會往下面看。

2.該方式好處在於載入完畢之後,就所有圖片都載入完畢了,體驗比較好。如果圖片全部過大,載入時間會比較長,loading 的時間也會很長,會影響體驗。

demo地址:github.com/chenhuiYj/e…

5.懶載入

這個大家應該很熟悉了,簡單點說就是圖片一開始不載入,當使用者瀏覽到什麼位置的時候,相應位置得圖片就載入出來。

[盤點] 專案中可以怎麼優化圖片

<body>
    <p><img data-src="lawyerOtherImg.jpg" class="load-img" width='528' height='304'/></p>
    <p><img data-src="lawyerOtherImg.jpg" class="load-img" width='528' height='304'/></p>
    <p><img data-src="lawyerOtherImg.jpg" class="load-img" width='528' height='304'/></p>
    <p><img data-src="https://materialdb.zhaoyl.com/201809/105567.jpg" class="load-img" width='528' height='304'/></p>
    <p><img data-src="https://materialdb.zhaoyl.com/201809/106796.jpg" class="load-img" width='528' height='304'/></p>
    <p><img data-src="https://materialdb.zhaoyl.com/201809/103097.jpg" class="load-img" width='528' height='304'/></p>
    <p><img data-src="https://materialdb.zhaoyl.com/201809/10205.jpg" class="load-img" width='528' height='304'/></p>
    <p><img data-src="https://materialdb.zhaoyl.com/201809/001.jpg" class="load-img" width='528' height='304'/></p>
</body>
複製程式碼
window.onload = function () {
    //根據load-img 這個 class 遍歷,元素距離頁面底部 100畫素的時候就開始載入,載入錯誤就顯示error.jpg
    ecDo.delayFn(ecDo.lazyLoadImg('load-img', 100, 'error.jpg'),100,200);
    window.onscroll = function () {
        ecDo.delayFn(ecDo.lazyLoadImg('load-img', 100, 'error.jpg'),100,200);
    }
}
複製程式碼

demo:github.com/chenhuiYj/e…

6.圖片沒載入出來顯示預設圖片

這個例子,當網速比較慢的時候,想要載入的圖片沒有馬上出來。或者圖片路徑錯誤,這個時候頁面可能會出現一部分空白的地方,或者頁面佈局會出現錯亂,比較常用的做法是先顯示一張 loading 圖或者是 logo 圖。告訴使用者,這裡是圖片,正在載入,體驗上會好很多,比如下面這個例子。

[盤點] 專案中可以怎麼優化圖片

下面也簡單的實現一下。

比如網站上有這樣的圖片

<p><img src="error.jpg" data-src="https://materialdb.zhaoyl.com/201809/105567.jpg" width="264"/></p>
<p><img src="error.jpg" data-src="https://materialdb.zhaoyl.com/201809/106796.jpg" width='264'/></p>
<p><img src="error.jpg" data-src="https://materialdb.zhaoyl.com/201809/1067961.jpg" width='264'/></p>
複製程式碼

在 network 把網速調至了慢速的3G,以方便除錯。

//測試前請先清空快取
window.onload = function () {
    let oImg=document.getElementsByTagName('img');
    for(let i=0;i<oImg.length;i++){
        ecDo.aftLoadImg({
            dom:oImg[i],
            url:oImg[i].dataset.src,
            errorUrl:oImg[i].src
        })
    }
}
複製程式碼

[盤點] 專案中可以怎麼優化圖片

可以看到,一開始顯示的是一張預設圖片,等需要載入的圖片,載入完了之後,再載入需要載入的圖片。(最後一張圖片,是故意把路徑寫錯,所以出來的圖片是之前的圖片)

demo:github.com/chenhuiYj/e…

7.小結

關於專案上,優化圖片的各種方式,自己用過的,聽過的,大概就在這裡了。實現方案,也不敢說是最好。如果大家有更好的想法,建議,歡迎在評論區留言。

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

想了解更多,和我交流,內推職位,請新增我微信。或者關注我的微信公眾號:守候書閣

[盤點] 專案中可以怎麼優化圖片[盤點] 專案中可以怎麼優化圖片

相關文章