用 HTML 和 CSS 制作 LOGO 動畫要比以前更容易,通過使用最新的 JavaScript 庫也能夠使網頁動畫制作的更加精良。
在本文中,我們將與大家分享 10 個讓人印象深刻的世界知名品牌與未知實體的自定義 LOGO 動畫示例。一起來 Enjoy 吧!
SVG 動畫作為網上最熱門的動畫趨勢之一,備受大家的關注。而這個花的 LOGO 動畫便是一個很好的 SVG 動畫示例。
我們可以看到,此 LOGO 的圖標和文字在<svg>標簽內編寫,通過 CSS 來控制動畫,并可以自動的完成頁面的加載。當然,需要一些 SVG 特定的 CSS 屬性支持,例如stroke-dashoffset(譯者:表示虛線的起始偏移),它會按順序來推動輪廓的運動,進而實現了精美的動畫效果。
項目地址:https://codepen.io/flwrs/pen/gLrygN
Carbon LDP 的 LOGO 動畫相當的復雜。但是開發者 David McFeders 通過 CSS/Compass 實現了 Carbon 的 LOGO 動畫,從而也提升了它的逼格。
無論是 LOGO 的大小,還是動畫的速度都很容易設置。它由純 CSS 實現,并保持著無限的循環。雖然,LOGO 的字母是一張 PNG 圖片,但你也可以隨時利用自己設計的字體進行逆向工程。
項目地址:https://codepen.io/MiguelAraCo/pen/QbZqoQ
Binary Lab 的 LOGO 動畫同樣是本文中比較復雜的動畫效果之一。我們可以看到它的效果:從燒瓶里拉出的數字,在 LOGO 的上方不斷的消失。
動畫效果是由 CSS 控制的。同時,這個作品依賴了 TweenMax 庫來添加重復的數字,并完成自定義的 alpha 轉換。作者很有創意的利用 CSS 與 JS 實現了這個酷炫的 Web 動畫效果。
項目地址:https://codepen.io/iconjunkie/pen/vLEaNZ
Stack Overflow 的 LOGO 是我最喜歡的 LOGO 之一,因為它的設計不僅簡單,而且易識別。而這個作品僅用 CSS3 將 Stack Overflow 的 LOGO 進行了動畫效果的實現。
這是迄今為止我看到的最令人印象深刻的純 CSS 動畫之一。最終的展現也與官方的 LOGO 很搭,同時在主流瀏覽器中動畫都可以流暢的運行。相信,任何喜歡 CSS / SCSS 動畫的朋友都會喜歡上這個作品。
項目地址:https://codepen.io/lindell/pen/mEVgJP
這個作品是由 Tim Pietrusky 利用 SVG 和均勻的 CSS 轉換實現的怪物能量 LOGO 系列動畫。如果你也打算在 LOGO 上實現淡入淡出的特效,就可以復制他的代碼來學習。
它是一款純 CSS 實現的動畫,所有的動畫時間都是由 SCSS 直接進行調控。同時,你也可以通過更改變量來調節動畫的速度,淡化顏色。
項目地址:https://codepen.io/TimPietrusky/pen/vKuja
Subvisual 團隊擁有非常獨特的 LOGO,而開發者 Miguel Palhas 則賦予了它酷炫的動畫效果。你會發現構成它的動畫效果有兩個因素,即 LOGO 的文字和“ S ”形圖標。
作品是基于 SVG 元素構成的,也使操縱更簡單。雖然作品中的大多數動畫都是基于 CSS 編寫的,但它也依賴 JavaScript 庫:TweenLite。同時,這個作品可以根據用戶的操作來重復或觸發動畫效果。(懸停、點擊等)
項目地址:https://codepen.io/naps62/pen/eNMvpQ
通過使用免費的像素字體,任何開發人員都可以制作出自定義的像素動畫。而這個作品就是由 CodePen 的用戶 Khaosmuhaha 所制作的。
他通過 HTML Canvas 元素進行純文本的操作,動畫效果則是由 CSS3 的 animation 屬性進行驅動,而 jQuery 則控制了全部。所以,我們所見的連續像素動畫就這樣實現了。
顯然,這是一個利用 Canvas 元素與 webfont 構成的炫酷的作品。
項目地址:https://codepen.io/Khaosmuhaha/pen/MYzRGz
如果你正在尋找一個真正復雜的 LOGO 動畫,可以看看開發者 Alex Aloia 制作的這個示例。在作品中,作者使用了他的名字作為品牌名稱,并將一系列復雜的 SVG 形狀通過繪圖的動畫效果展現出來。
作品的整體效果只通過 CSS 來實現是不太可能的,還需要一些 JS 庫 (DrawSVG 和更流行的 D3.js)的支持。但是,利用開源庫來實現這種獨一無二的動畫,還是非常有趣的。
項目地址:https://codepen.io/tripl3inf/pen/QwrEMY
Bayleys 的 LOGO 動畫的選擇,有些令人費解。但 LOGO 厚實的邊緣使重制變得易如反掌。開發者 Rafael Contreras 僅通過 38 行代碼便實現了動畫效果。
LOGO 是基于 SVG 標簽制作的,動畫效果則是操縱相應的標簽來實現。而在不同的方向移動的眾多 LOGO 元素,使動畫令人著迷。
項目地址:https://codepen.io/rafita/pen/aNyRgv
這是來自任天堂最新款游戲機的一個 LOGO 動畫。而開發者 Koto Furumiya 在 CodePen 上實現了它們廣告片中的動畫效果。
Koto 使用 SVG 重制了任天堂 Switch 的 LOGO,并用 CSS 實現了它的動畫效果。你會相信這個動畫只需要 50 行的 CSS 代碼嗎?
另外,不得不提這個動畫效果確實很逼真。強有力的下推與反彈回升效果,確實與任天堂 Switch 的開機動畫相吻合。
項目地址:https://codepen.io/kotofurumiya/pen/VPmNrR
今天分享的所有示例都是免費與開源的,希望你能將它們應用在你自己的項目上。同時,也希望你能喜歡這些 Demos。如果你正在尋找更多關于 CSS 動畫的示例,也可以了解下這個合輯。
感謝你的閱讀。
注:
本文版權歸原作者所有,僅用于學習與交流。
如需轉載譯文,煩請按下方注明出處信息,謝謝!
英文原文:10 Amazing Examples of CSS & JavaScript Animated Logos
作者:Jake Rocheleau
譯者:IT程序獅
譯文地址:http://www.jianshu.com/p/b204e854a942
文作者:HelloGitHub-kalifun
圖表庫千萬個今天 HelloGitHub 給大家推薦個很有“特色”的圖表庫:一個手繪風格的 JS 圖表庫 —— Chart.xkcd,快收起你緊繃、嚴肅的面容讓我們一起看看用手繪風格展示數據的效果。
一、介紹
項目地址:https://github.com/timqian/chart.xkcd
Chart.xkcd 是一個圖表庫,可繪制“非精細”、“卡通”或“手繪”樣式的圖表。
效果是不是很可愛?那下面就跟著 HelloGitHub 發起的《講解開源項目》[1]的教程一起學習、上手使用起來吧!
二、快速入手
使用 Chart.xkcd 很容易,只需頁面中包含庫的引用和一個用于顯示圖表的 <svg> 節點即可。
2.1 代碼示例
先用一段簡短的代碼,讓大家了解下基本的參數和代碼的樣子,后面會有可運行的代碼示例片段供大家學習和使用 。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--將 SVG 元素直接嵌入 HTML 頁面中--> <svg class="line-chart"></svg> <!--引入 JS 庫--> <script src="https://cdn.jsdelivr.net/npm/chart.xkcd@1.1/dist/chart.xkcd.min.js"></script> <script> //關鍵代碼塊 const svg=document.querySelector('.line-chart') new chartXkcd.Line(svg, { title: '', xLabel: '', yLabel: '', data: {...}, options: {}, }); </script> </body> </html>
2.2 參數說明
三、圖表類型
Chart.xkcd 支持多樣的圖表類型,下面將逐一講解和實現:折線圖、XY 圖、條形圖、圓餅/甜甜圈圖、雷達圖,實現的示例代碼完整可運行、注釋完整、包含參數說明。
tips:下文中的示例代碼均可直接運行,保存為 html 文件便可在本機查看效果。
3.1 折線圖
折線圖以折線形式顯示一系列數據點,它可以用于顯示趨勢數據或不同數據集的比較。
示例代碼
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--將 SVG 元素直接嵌入 HTML 頁面中--> <svg class="line-chart"></svg> <!--引入 JS 庫--> <script src="https://cdn.jsdelivr.net/npm/chart.xkcd@1.1/dist/chart.xkcd.min.js"></script> <script> // querySelector() 方法返回文檔中匹配指定 CSS 選擇器的一個元素。獲取文檔中 class=".line-chart" 的元素。 const svg=document.querySelector('.line-chart'); // chartXkcd.Line 創建一個折線圖 const lineChart=new chartXkcd.Line(svg, { //圖表的標題 title: 'Monthly income of an indie developer', // 圖表的 x 標簽 xLabel: 'Month', // 圖表的 y 標簽 yLabel: '$ Dollors', // 需要可視化的數據 data: { // x 軸數據 labels: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'], // y 軸數據 datasets: [{ // 第一組數據 label: 'Plan', data: [30, 70, 200, 300, 500, 800, 1500, 2900, 5000, 8000], }, { // 第二組數據 label: 'Reality', data: [0, 1, 30, 70, 80, 100, 50, 80, 40, 150], }], }, // 可選配置以自定義圖表的外觀 options: { // 自定義要在 y 軸上看到的刻度號(默認為 3) yTickCount: 3, // 指定要放置圖例的位置 legendPosition: chartXkcd.config.positionType.upLeft } }); </script> </body> </html>
參數說明
效果展示
3.2 XY 圖
XY 圖表用于通過指定點的 XY 坐標來繪制點,您也可以通過連接這些點來繪制 XY 折線圖。
示例代碼
<script> // querySelector() 方法返回文檔中匹配指定 CSS 選擇器的一個元素。獲取文檔中 class=".xy-chart" 的元素。 const svg=document.querySelector('.xy-chart'); //chartXkcd.XY 創建一個XY圖 new chartXkcd.XY(svg, { //圖表的標題 title: 'Pokemon farms', // 圖表的 x 標簽 xLabel: 'Coodinate', // 圖表的 y 標簽 yLabel: 'Count', // 需要可視化的數據 data: { datasets: [{ // 第一組數據 label: 'Pikachu', data: [{ x: 3, y: 10 }, { x: 4, y: 122 }, { x: 10, y: 100 }, { x: 1, y: 2 }, { x: 2, y: 4 }], }, { // 第二組數據 label: 'Squirtle', data: [{ x: 3, y: 122 }, { x: 4, y: 212 }, { x: -3, y: 100 }, { x: 1, y: 1 }, { x: 1.5, y: 12 }], }], }, options: { // 自定義要在 x 軸上看到的刻度號(默認為 3) xTickCount: 5, // 自定義要在 y 軸上看到的刻度號(默認為 3) yTickCount: 5, // 指定要放置圖例的位置 legendPosition: chartXkcd.config.positionType.upRight, // 用線連接點(默認 false) showLine: false, // 指定時間格式 timeFormat: undefined, // 更改點的大小(默認為 1) dotSize: 1, }, }); </script>
參數說明
效果展示
如果你想將這些點連接起來,讓數據對比更加明顯的話。請修改 showLine:true 再刷新頁面你就可以看到連線的效果了。
3.3 條形圖
條形圖提供了一種顯示以豎條表示的數據值的方式。
示例代碼
<script> // querySelector() 方法返回文檔中匹配指定 CSS 選擇器的一個元素。獲取文檔中 class=".bar-chart" 的元素。 const svg=document.querySelector('.bar-chart'); // chartXkcd.Bar 創建一個條形圖 const barChart=new chartXkcd.Bar(svg, { // 圖表的標題 title: 'github stars VS patron number', // xLabel: '', // optional // yLabel: '', // optional // 圖表數據 data: { labels: ['github stars', 'patrons'], datasets: [{ data: [100, 2], }], }, options: { // 自定義要在 y 軸上看到的刻度號(默認為 3) yTickCount: 2, }, }); </script>
參數說明
效果展示
3.4 圓餅/甜甜圈圖
餅圖廣泛得應用在各個領域,用于表示不同分類的占比情況,通過弧度大小來對比各種分類。餅圖通過將一個圓餅按照分類的占比劃分成多個區塊,整個圓餅代表數據的總量,每個區塊(圓弧)表示該分類占總體的比例大小,所有區塊(圓弧)的加和等于 100%。
示例代碼
<script> // querySelector() 方法返回文檔中匹配指定 CSS 選擇器的一個元素。獲取文檔中 class=".pie-chart" 的元素。 const svg=document.querySelector('.pie-chart'); // chartXkcd.Pie 創建一個圓餅圖 const pieChart=new chartXkcd.Pie(svg, { // 圖表的標題 title: 'What Tim made of', // 需要可視化的數據 data: { labels: ['a', 'b', 'e', 'f', 'g'], datasets: [{ data: [500, 200, 80, 90, 100], }], }, options: { // 指定空的餅圖半徑 innerRadius: 0.5, // 指定要放置圖例的位置 legendPosition: chartXkcd.config.positionType.upRight, }, }); </script>
參數說明
效果展示
3.5 雷達圖
雷達圖(Radar Chart)又被叫做蜘蛛網圖,適用于顯示三個或更多的維度的變量。雷達圖是以在同一點開始的軸上顯示的三個或更多個變量的二維圖表的形式來顯示多元數據的方法,其中軸的相對位置和角度通常是無意義的。
示例代碼
<script> // querySelector() 方法返回文檔中匹配指定 CSS 選擇器的一個元素。獲取文檔中 class=".radar-chart" 的元素。 const svg=document.querySelector('.radar-chart'); // chartXkcd.Radar 創建一個雷達圖 const radarChart=new chartXkcd.Radar(svg, { // 圖表的標題 title: 'Letters in random words', // 需要可視化的數據 data: { labels: ['c', 'h', 'a', 'r', 't'], datasets: [{ label: 'ccharrrt', data: [2, 1, 1, 3, 1], }, { label: 'chhaart', data: [1, 2, 2, 1, 1], }], }, options: { // 在圖表中顯示圖例 showLegend: true, // 點的大小 dotSize: 0.8, // 在每行附近顯示標簽 showLabels: true, // 指定要放置圖例的位置 legendPosition: chartXkcd.config.positionType.upRight, // unxkcdify: true, }, }); </script>
參數說明
效果展示
四、最后
以上就是講解的全部內容,相信教程至此 Chart.xkcd 庫的基本用法你已經基本掌握,后面就可以用來今天學到的東西,提高自己項目的顏值了。
有了 Chart.xkcd 讓數據可愛地展示出來并不難,快動手自己實現一個吧~
參考資料
[1]《講解開源項目》: https://github.com/HelloGitHub-Team/Article
[2]CHART.XKCD 官方文檔: https://timqian.com/chart.xkcd/
[3]CHART.XKCD 項目地址: https://github.com/timqian/chart.xkcd
『講解開源項目系列』——讓對開源項目感興趣的人不再畏懼、讓開源項目的發起者不再孤單。跟著我們的文章,你會發現編程的樂趣、使用和發現參與開源項目如此簡單。歡迎留言聯系我們、加入我們,讓更多人愛上開源、貢獻開源~
接:https://juejin.im/book/5b936540f265da0a9624b04b
《高性能網站建設指南》的作者 Steve Souders 曾在一篇博客中提到:
我的大部分性能優化工作都集中在 JavaScript 和 CSS 上,從早期的 Move Scripts to the Bottom 和 Put Stylesheets at the Top 規則。為了強調這些規則的重要性,我甚至說過,“JS 和 CSS 是頁面上最重要的部分”。
幾個月后,我意識到這是錯誤的。圖片才是頁面上最重要的部分。
我關注 JS 和 CSS 的重點也是如何能夠更快地下載圖片。圖片是用戶可以直觀看到的。他們并不會關注 JS 和 CSS。確實,JS 和 CSS 會影響圖片內容的展示,尤其是會影響圖片的展示方式(比如圖片輪播,CSS 背景圖和媒體查詢)。但是我認為 JS 和 CSS 只是展示圖片的方式。在頁面加載的過程中,應當先讓圖片和文字先展示,而不是試圖保證 JS 和 CSS 更快下載完成。
這段話可謂字字珠璣。此外,雅虎軍規和 Google 官方的最佳實踐也都將圖片優化列為前端性能優化必不可少的環節——圖片優化的優先級可見一斑。
就圖片這塊來說,與其說我們是在做“優化”,不如說我們是在做“權衡”。因為我們要做的事情,就是去壓縮圖片的體積(或者一開始就選取體積較小的圖片格式)。但這個優化操作,是以犧牲一部分成像質量為代價的。因此我們的主要任務,是盡可能地去尋求一個質量與性能之間的平衡點。
2019 年,圖片依然很大
這里先給大家介紹 HTTP-Archive 這個網站,它會定期抓取 Web 上的站點,并記錄資源的加載情況、Web API 的使用情況等頁面的詳細信息,并會對這些數據進行處理和分析以確定趨勢。通過它我們可以實時地看到世界范圍內的 Web 資源的統計結果。
截止到 2018 年 8 月,過去一年總的 web 資源的平均請求體積是這樣的:
而具體到圖片這一類的資源,平均請求體積是這樣的:
當然,隨著我們工程師在性能方面所做的努力越來越有成效,平均來說,不管是資源總量還是圖片體積,都在往越來越輕量的方向演化。這是一種值得肯定的進步。
但同時我們不得不承認,如圖所示的這個圖片體積,依然是太大了。圖片在所有資源中所占的比重,也足夠“觸目驚心”了。為了改變這個現狀,我們必須把圖片優化提上日程。
時下應用較為廣泛的 Web 圖片格式有 JPEG/JPG、PNG、WebP、Base64、SVG 等,這些格式都是很有故事的,值得我們好好研究一把。此外,老生常談的雪碧圖(CSS Sprites)至今也仍在一線的前端應用中發光發熱,我們也會有所提及。
不談業務場景的選型都是耍流氓。下面我們就結合具體的業務場景,一起來解開圖片選型的神秘面紗!
在計算機中,像素用二進制數來表示。不同的圖片格式中像素與二進制位數之間的對應關系是不同的。一個像素對應的二進制位數越多,它可以表示的顏色種類就越多,成像效果也就越細膩,文件體積相應也會越大。
一個二進制位表示兩種顏色(0|1 對應黑|白),如果一種圖片格式對應的二進制位數有 n 個,那么它就可以呈現 2^n 種顏色。
關鍵字:有損壓縮、體積小、加載快、不支持透明
JPG 的優點
JPG 最大的特點是有損壓縮。這種高效的壓縮算法使它成為了一種非常輕巧的圖片格式。另一方面,即使被稱為“有損”壓縮,JPG的壓縮方式仍然是一種高質量的壓縮方式:當我們把圖片體積壓縮至原有體積的 50% 以下時,JPG 仍然可以保持住 60% 的品質。此外,JPG 格式以 24 位存儲單個圖,可以呈現多達 1600 萬種顏色,足以應對大多數場景下對色彩的要求,這一點決定了它壓縮前后的質量損耗并不容易被我們人類的肉眼所察覺——前提是你用對了業務場景。
使用場景
JPG 適用于呈現色彩豐富的圖片,在我們日常開發中,JPG 圖片經常作為大的背景圖、輪播圖或 Banner 圖出現。
兩大電商網站對大圖的處理,是 JPG 圖片應用場景的最佳寫照:
打開淘寶首頁,我們可以發現頁面中最醒目、最龐大的圖片,一定是以 .jpg 為后綴的:
京東首頁也不例外:
使用 JPG 呈現大圖,既可以保住圖片的質量,又不會帶來令人頭疼的圖片體積,是當下比較推崇的一種方案。
JPG 的缺陷
有損壓縮在上文所展示的輪播圖上確實很難露出馬腳,但當它處理矢量圖形和 Logo 等線條感較強、顏色對比強烈的圖像時,人為壓縮導致的圖片模糊會相當明顯。
此外,JPEG 圖像不支持透明度處理,透明圖片需要召喚 PNG 來呈現。
關鍵字:無損壓縮、質量高、體積大、支持透明
PNG 的優點
PNG(可移植網絡圖形格式)是一種無損壓縮的高保真的圖片格式。8 和 24,這里都是二進制數的位數。按照我們前置知識里提到的對應關系,8 位的 PNG 最多支持 256 種顏色,而 24 位的可以呈現約 1600 萬種顏色。
PNG 圖片具有比 JPG 更強的色彩表現力,對線條的處理更加細膩,對透明度有良好的支持。它彌補了上文我們提到的 JPG 的局限性,唯一的 BUG 就是體積太大。
PNG-8 與 PNG-24 的選擇題
什么時候用 PNG-8,什么時候用 PNG-24,這是一個問題。
理論上來說,當你追求最佳的顯示效果、并且不在意文件體積大小時,是推薦使用 PNG-24 的。
但實踐當中,為了規避體積的問題,我們一般不用PNG去處理較復雜的圖像。當我們遇到適合 PNG 的場景時,也會優先選擇更為小巧的 PNG-8。
如何確定一張圖片是該用 PNG-8 還是 PNG-24 去呈現呢?好的做法是把圖片先按照這兩種格式分別輸出,看 PNG-8 輸出的結果是否會帶來肉眼可見的質量損耗,并且確認這種損耗是否在我們(尤其是你的 UI 設計師)可接受的范圍內,基于對比的結果去做判斷。
應用場景
前面我們提到,復雜的、色彩層次豐富的圖片,用 PNG 來處理的話,成本會比較高,我們一般會交給 JPG 去存儲。
考慮到 PNG 在處理線條和顏色對比度方面的優勢,我們主要用它來呈現小的 Logo、顏色簡單且對比強烈的圖片或背景等。
此時我們再次把目光轉向性能方面堪稱業界楷模的淘寶首頁,我們會發現它頁面上的 Logo,無論大小,還真的都是 PNG 格式:
主 Logo:
較小的 Logo:
顏色簡單、對比度較強的透明小圖也在 PNG 格式下有著良好的表現:
關鍵字:文本文件、體積小、不失真、兼容性好
SVG(可縮放矢量圖形)是一種基于 XML 語法的圖像格式。它和本文提及的其它圖片種類有著本質的不同:SVG 對圖像的處理不是基于像素點,而是是基于對圖像的形狀描述。
SVG 的特性
和性能關系最密切的一點就是:SVG 與 PNG 和 JPG 相比,文件體積更小,可壓縮性更強。
當然,作為矢量圖,它最顯著的優勢還是在于圖片可無限放大而不失真這一點上。這使得 SVG 即使是被放到視網膜屏幕上,也可以一如既往地展現出較好的成像品質——1 張 SVG 足以適配 n 種分辨率。
此外,SVG 是文本文件。我們既可以像寫代碼一樣定義 SVG,把它寫在 HTML 里、成為 DOM 的一部分,也可以把對圖形的描述寫入以 .svg 為后綴的獨立文件(SVG 文件在使用上與普通圖片文件無異)。這使得 SVG 文件可以被非常多的工具讀取和修改,具有較強的靈活性。
SVG 的局限性主要有兩個方面,一方面是它的渲染成本比較高,這點對性能來說是很不利的。另一方面,SVG 存在著其它圖片格式所沒有的學習成本(它是可編程的)。
SVG 的使用方式與應用場景
SVG 是文本文件,我們既可以像寫代碼一樣定義 SVG,把它寫在 HTML 里、成為 DOM 的一部分,也可以把對圖形的描述寫入以 .svg 為后綴的獨立文件(SVG 文件在使用上與普通圖片文件無異)。
將 SVG 寫入 HTML:
將 SVG 寫入獨立文件后引入 HTML:
<img src="文件名.svg" alt="">
在實際開發中,我們更多用到的是后者。很多情況下設計師會給到我們 SVG 文件,就算沒有設計師,我們還有非常好用的 在線矢量圖形庫。對于矢量圖,我們無須深究過多,只需要對其核心特性有所掌握、日后在應用時做到有跡可循即可。
關鍵字:文本文件、依賴編碼、小圖標解決方案
Base64 并非一種圖片格式,而是一種編碼方式。Base64 和雪碧圖一樣,是作為小圖標解決方案而存在的。在了解 Base64 之前,我們先來了解一下雪碧圖。
前置知識:最經典的小圖標解決方案——雪碧圖(CSS Sprites)
雪碧圖、CSS 精靈、CSS Sprites、圖像精靈,說的都是這個東西——一種將小圖標和背景圖像合并到一張圖片上,然后利用 CSS 的背景定位來顯示其中的每一部分的技術。
MDN 對雪碧圖的解釋已經非常到位:
圖像精靈(sprite,意為精靈),被運用于眾多使用大量小圖標的網頁應用之上。它可取圖像的一部分來使用,使得使用一個圖像文件替代多個小文件成為可能。相較于一個小圖標一個圖像文件,單獨一張圖片所需的 HTTP 請求更少,對內存和帶寬更加友好。
我們幾乎可以在每一個有小圖標出現的網站里找到雪碧圖的影子(下圖截取自京東首頁):
和雪碧圖一樣,Base64 圖片的出現,也是為了減少加載網頁圖片時對服務器的請求次數,從而提升網頁性能。Base64 是作為雪碧圖的補充而存在的。
理解 Base64
通過我們上文的演示,大家不難看出,每次加載圖片,都是需要單獨向服務器請求這個圖片對應的資源的——這也就意味著一次 HTTP 請求的開銷。
Base64 是一種用于傳輸 8Bit 字節碼的編碼方式,通過對圖片進行 Base64 編碼,我們可以直接將編碼結果寫入 HTML 或者寫入 CSS,從而減少 HTTP 請求的次數。
我們來一起看一個實例,現在我有這么一個小小的放大鏡 Logo:
它對應的鏈接如下:
https://user-gold-cdn.xitu.io/2018/9/15/165db7e94699824b?w=22&h=22&f=png&s=3680
按照一貫的思路,我們加載圖片需要把圖片鏈接寫入 img 標簽:
<img src="https://user-gold-cdn.xitu.io/2018/9/15/165db7e94699824b?w=22&h=22&f=png&s=3680">
瀏覽器就會針對我們的圖片鏈接去發起一個資源請求。
但是如果我們對這個圖片進行 Base64 編碼,我們會得到一個很長很長的字符串,我們可以直接用這個字符串替換掉上文中的鏈接地址。你會發現瀏覽器原來是可以理解這個字符串的,它自動就將這個字符串解碼為了一個圖片,而不需再去發送 HTTP 請求。
Base64 的應用場景
上面這個實例,其實源自我們 掘金 網站 Header 部分的搜索欄 Logo:
既然 Base64 這么棒,我們何不把大圖也換成 Base64 呢?
這是因為,Base64 編碼后,圖片大小會膨脹為原文件的 4/3(這是由 Base64 的編碼原理決定的)。如果我們把大圖也編碼到 HTML 或 CSS 文件中,后者的體積會明顯增加,即便我們減少了 HTTP 請求,也無法彌補這龐大的體積帶來的性能開銷,得不償失。
在傳輸非常小的圖片的時候,Base64 帶來的文件體積膨脹、以及瀏覽器解析 Base64 的時間開銷,與它節省掉的 HTTP 請求開銷相比,可以忽略不計,這時候才能真正體現出它在性能方面的優勢。
因此,Base64 并非萬全之策,我們往往在一張圖片滿足以下條件時會對它應用 Base64 編碼:
Base64 編碼工具推薦
這里最推薦的是利用 webpack 來進行 Base64 的編碼——webpack 的 url-loader 非常聰明,它除了具備基本的 Base64 轉碼能力,還可以結合文件大小,幫我們判斷圖片是否有必要進行 Base64 編碼。
除此之外,市面上免費的 Base64 編解碼工具種類是非常多樣化的,有很多網站都提供在線編解碼的服務,大家選取自己認為順手的工具就好。
關鍵字:年輕的全能型選手
WebP 是今天在座各類圖片格式中最年輕的一位,它于 2010 年被提出, 是 Google 專為 Web 開發的一種旨在加快圖片加載速度的圖片格式,它支持有損壓縮和無損壓縮。
WebP 的優點
WebP 像 JPEG 一樣對細節豐富的圖片信手拈來,像 PNG 一樣支持透明,像 GIF 一樣可以顯示動態圖片——它集多種圖片文件格式的優點于一身。
WebP 的官方介紹對這一點有著更權威的闡述:
與 PNG 相比,WebP 無損圖像的尺寸縮小了 26%。在等效的 SSIM 質量指數下,WebP 有損圖像比同類 JPEG 圖像小 25-34%。 無損 WebP 支持透明度(也稱為 alpha 通道),僅需 22% 的額外字節。對于有損 RGB 壓縮可接受的情況,有損 WebP 也支持透明度,與 PNG 相比,通常提供 3 倍的文件大小。
我們開篇提到,圖片優化是質量與性能的博弈,從這個角度看,WebP 無疑是真正的贏家。
WebP 的局限性
WebP 縱有千般好,但它畢竟太年輕。我們知道,任何新生事物,都逃不開兼容性的大坑。現在是 2018 年 9 月,WebP 的支持情況是這樣的:
坦白地說,雖然沒有特別慘(畢竟還有親爹 Chrome 在撐腰),但也足夠讓人望而卻步了。
此外,WebP 還會增加服務器的負擔——和編碼 JPG 文件相比,編碼同樣質量的 WebP 文件會占用更多的計算資源。
WebP 的應用場景
現在限制我們使用 WebP 的最大問題不是“這個圖片是否適合用 WebP 呈現”的問題,而是“瀏覽器是否允許 WebP”的問題,即我們上文談到的兼容性問題。具體來說,一旦我們選擇了 WebP,就要考慮在 Safari 等瀏覽器下它無法顯示的問題,也就是說我們需要準備 PlanB,準備降級方案。
目前真正把 WebP 格式落地到網頁中的網站并不是很多,這其中淘寶首頁對 WebP 兼容性問題的處理方式就非常有趣。我們可以打開 Chrome 的開發者工具搜索其源碼里的 WebP 關鍵字:
我們會發現檢索結果還是挺多的(單就圖示的加載結果來看,足足有?200?多條),下面大家注意一下這些 WebP 圖片的鏈接地址(以其中一個為例):
<img src="http://img.alicdn.com/tps/i4/TB1CKSgIpXXXXccXXXX07tlTXXX-200-200.png_60x60.jpg_.webp" alt="手機app - 聚劃算" class="app-icon">
.webp 前面,還跟了一個 .jpg 后綴!
我們現在先大膽地猜測,這個圖片應該至少存在 jpg 和 webp 兩種格式,程序會根據瀏覽器的型號、以及該型號是否支持 WebP 這些信息來決定當前瀏覽器顯示的是 .webp 后綴還是 .jpg 后綴。帶著這個預判,我們打開并不支持 WebP 格式的 Safari 來進入同樣的頁面,再次搜索 WebP 關鍵字:
Safari 提示我們找不到,這也是情理之中。我們定位到剛剛示例的 WebP 圖片所在的元素,查看一下它在 Safari 里的圖片鏈接:
<img src="http://img.alicdn.com/tps/i4/TB1CKSgIpXXXXccXXXX07tlTXXX-200-200.png_60x60.jpg" alt="手機app - 聚劃算" class="app-icon">
我們看到同樣的一張圖片,在 Safari 中的后綴從 .webp 變成了 .jpg!看來果然如此——站點確實是先進行了兼容性的預判,在瀏覽器環境支持 WebP 的情況下,優先使用 WebP 格式,否則就把圖片降級為 JPG 格式(本質是對圖片的鏈接地址作簡單的字符串切割)。
此外,還有另一個維護性更強、更加靈活的方案——把判斷工作交給后端,由服務器根據 HTTP 請求頭部的 Accept 字段來決定返回什么格式的圖片。當 Accept 字段包含 image/webp 時,就返回 WebP 格式的圖片,否則返回原圖。這種做法的好處是,當瀏覽器對 WebP 格式圖片的兼容支持發生改變時,我們也不用再去更新自己的兼容判定代碼,只需要服務端像往常一樣對 Accept 字段進行檢查即可。
由此也可以看出,我們 WebP 格式的局限性確實比較明顯,如果決定使用 WebP,兼容性處理是必不可少的。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。