雪碧圖在縮放場景下的特殊處理

發表於2016-07-13

回想n年前剛寫前端的時候,在處理一個’滑鼠hover切換背景圖會閃’的問題時,將兩張背景圖合成一張圖片,順利解決問題。這應該是我第一次用到雪碧圖的情況。

1

雪碧圖作為背景在切換時不會有因為需要等待下載而產生的閃現

如今,開啟一個站點,呈現鋪天蓋地的圖片資源的頁面隨處可見。而多數站點更會用一套包含幾十個風格統一的圖示的圖示庫,加之移動端的佔比與日俱增,雪碧圖這項技術被運用的就越來越普遍。

最簡單,最實用的使用方法

得益於偽元素的功勞,在不破壞頁面結構,不增加多餘標籤的情況下,通過::after建立一個你所需要圖示大小的偽元素,並將所需要的圖示通過background-position定位到指定的空間,對應的圖示變順利地呈現出來。

asdfasdfadf
通過偽元素實現的圖示

一些問題

看上去貌似是一個完美的解決方案,然而真的是這樣麼?我們來看一個例子:

fafafafafafafafffff

一個介面

目前有這麼一個簡單的頁面(無視它的設計合理性吧),拿到手後擼起袖子就寫。切圖切著切著貌似哪裡不對。。。恩!三個鈴鐺不是同一個圖片大小不同而已麼?明顯有優化的餘地啊!只要切一個圖來個調整下尺寸不就解決了麼~~

恩恩恩。在普通的頁面中,來個backgroud-size妥妥地解決。

當我們按部就班地把屬性設定到雪碧圖上時,可以發現,呈現出的效果完全不是之前設想的那樣。尺寸、定位完全不對。哪裡出了問題了呢?原理很簡單。background-size並不感知icon的存在,我們想只針對icon進行配置,而這個屬性其實是作用於整個雪碧圖上的。

隨之而來的解決方案

回想整個渲染執行的流程:

  1. background-size 作用於整個雪碧圖,對其尺寸縮放。
  2. background-position 定位。

那麼要得到正確的效果的話,以放大兩倍為例,需要做到:

  1. 將偽元素的尺寸擴大2倍

  2. 將整個雪碧圖的尺寸擴大2倍

  3. 將座標偏移量相應擴大2倍

cafdasdfeafdsaf
圖片

綜上,如果想在雪碧圖內實現縮放邏輯,必須通過

  • 雪碧圖長寬
  • 該圖示原始長寬
  • 該圖示在雪碧圖中的偏移量

總共6個變數去實現。用動態樣式語言的話,或許可以得到這麼一個通用函式:

以上,我們完成了把雪碧圖中的圖示縮放後呈現在頁面上的這一目標。

怎麼樣,看到這個解決方案,有沒有一種把程式碼刪光,把大中小三個圖示都塞進雪碧圖的衝動?

冷靜一下,再想想方案

不就是縮放麼?background-size會扯出這麼多問題,不是還有個transform麼?會出現同樣的問題麼? 那麼要得到正確的效果的話,以放大兩倍為例,需要做到: 恩?好像就加一行程式碼?

好吧,就是這樣。兩者區別也很簡單,因為一個作用在元素上,一個作用在雪碧圖上,所以後者會帶出n多副作用。

那麼如果需要縮放到固定尺寸時,還需要知曉原始尺寸,通過計算得到一個縮放係數,這樣才能最終達到所需的效果。

最後的總結

回顧一下,一個簡單的縮放需求,出現了三種解決方案:

  1. 最無腦的全部放進雪碧圖中
  2. 最冗長的修改background-size
  3. 以及最簡短的transform變形

一般情況下,還是無視第二種方案吧。那麼在1和3兩者中間,則各有取捨。現在回想整個尋求解決方案的過程,個人還是比較傾向方案1的,畢竟,幾乎沒有什麼出錯的可能。而且都是同一張雪碧圖,並沒有更多的請求數,只是多了點圖片大小而已。

相關參考資料

一種雪碧圖自動化方案的設想

MDN:background-size

相關文章