深刻淺出CSS(二):關於雪碧圖、background-position與steps函數的三角戀情

【測試代碼】html

HTMLweb

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta http-equiv="X-UA-Compatible" content="id=edge">
 6     <meta name="viewport" content="width=device-width,initial-scale=1.0">
 7     <title>雪碧圖練習</title>
 8 </head>
 9 <body>
10     <div class="footer">
11         <div class="wrap">
12             <div class="pic pic1 move"></div>
13             <div class="pic pic2 move "></div>
14             <div class="pic pic3 move"></div>
15             <div class="pic pic4 move"></div>
16         </div>
17     </div>
18 </body>
19 </html>

 

CSS編輯器

 1 *{margin: 0;padding: 0;}
 2 html,body {
 3     width: 100%;
 4     height: 100%;
 5 }
 6  .footer {
 7      position: relative;
 8      width: 100%;
 9      height: 100%;
10      background: url("https://xyq.res.netease.com/pc/gw/20170118103441/img/ft_e43a6db.webp") 0 0 no-repeat;
11         overflow: hidden: /*造成BFC盒模型,保證.wrap的margin在.footer內移動*/
12  }
13  .wrap {
14      width: 780px;
15      margin: 320px auto 0; /*未設置overflow: hidden;,保證在圖片調整位置時的溢出仍能顯示*/
16  }
17  .pic {
18      float: left;
19  }
20  .pic1 {
21      width: 200px;
22      height: 180px;
23      background: url("https://xyq.res.netease.com/pc/gw/20170118103441/img/west_01_3ca39fe.png") 0 0 no-repeat;
24  }
25  .pic2 {
26      width: 200px;
27      height: 180px;
28      background: url("https://xyq.res.netease.com/pc/gw/20170118103441/img/west_02_47bad19.png") 0 0 no-repeat;
29  }
30  .pic3 {
31      width: 170px;
32      height: 240px;
33      background: url("https://xyq.res.netease.com/pc/gw/20170118103441/img/west_03_f962447.png") 0 0 no-repeat;
34      margin-top: -30px;
35  }
36  .pic4 {
37      width: 210px;
38      height: 200px;
39      background: url("https://xyq.res.netease.com/pc/gw/20170118103441/img/west_04_6516d80.png") 0 0 no-repeat;
40  }
41  
42  /*動畫*/
43 @keyframes move {
44     0% {
45         background-position: 0 0;
46     }
47     100% {
48         background-position: 114.2857% 0;
49     }
50 }
51 
52 .move {
53     -webkit-animation: move 1.4s steps(8) infinite;
54     -o-animation: move 1.4s steps(8) infinite;
55     animation: move 1.4s steps(8) infinite;
56 }
57     

 

 

1、概念理解函數

 1.什麼是雪碧圖??測試

  CSS雪碧的基本原理,是把你的網站上用到的一些圖片整合到一張單獨的圖片中,從而減小你的網站的HTTP請求數量。該圖片使用CSS的background和background-position屬性渲染,達到加在一次圖片,能夠實現複雜圖片的效果,提升頁面在使用時的效果響應速度。但相應的,缺點也十分明顯,就是提升了頁面的加載時間。動畫

  CSS雪碧圖的基本應用大多在鼠標滑過以及一些動圖效果。網站

  2.什麼是background和background-position??ui

  根據W3C的標準定義,background就是聲明元素背景的屬性,共有以下屬性值:url

    • background-color
    • background-position
    • background-size
    • background-repeat
    • background-origin
    • background-clip
    • background-attachment
    • background-image

  具體每一個屬性的含義及用法,這裏再也不闡述。spa

  從上咱們能夠看到,background-position是background衆多屬性中的一種。其含義就是聲明背景在元素中的位置。其計算方式以下圖所示:

  

   這裏邊的計算,由易到難,我一一進行一個簡單的梳理。首先要明確的一點,全部位置的計算,都是基於元素的background-clip設定區域(若是未設置background-clip的話,就是元素的border-box)。明確了計算區域後,下面再來講計算規則:

   計算規則總共分爲兩大類,一類是根據設定好規則的方向值來聲明位置。另外一類是根據肯定的數值或百分比來計算位置。

 

   1.首先是五個方向top lright bottom left center的計算。這個的位置是相對固定的。設定值總共有兩個,默認爲center。理解起來也很簡單——就是把兩個單詞倒過來讀。舉個例子,top left就是左上角、bottom right就是右下角。

    

 

    2.而後是設定固定值或百分比,這兩類都是根據肯定的數值,在X、Y軸上進行調整。區別就是固定值是直接根據聲明值進行調整,而百分比是由(背景區域的寬度/高度 - 圖片的寬度/高度)*(X)%的計算式計算後的數值在X、Y軸上進行調整。

       

      1)固定值聲明的位移

     

 

      2)百分比聲明的計算

    

  

 

    結合上圖,理解結論:1)固定值聲明,正值即沿X、Y軸方向進行位移。負值即沿反方向位移;

              2)百分比聲明,當圖片寬度大於實際背景尺寸時(雪碧圖原理),百分比正值時,計算值即爲負;百分比負值時,計算值即爲正。方向調整邏輯與固定值聲明相同;

 

      好了,概念介紹完畢,下面進入正題。

 

2、雪碧圖與background-position的愛恨糾纏

    1.直接上例子

    以網易夢幻西遊官網的底部雪碧圖爲例——傳送門http://xyq.163.com/

    

 

 

  

  從上面兩張夢幻西遊官網的圖中能夠看到,雪碧圖由師徒四人共四張圖片造成,而且每一個圖片都單獨設置了動畫樣式。由此不難猜出,這個雪碧圖是根據每一個圖片的實際寬度,經過steps屬性,設定了固定的background值來完成的。大體代碼以下:

/*假定圖片寬度1600px*/
@keyframes play {
    from {background-position: 0 0;}     
    to {background-position: -1600px 0}
}

/*應用動畫*/
.west-x {
animation: play 1.4s steps(8,end) infinite;
}

 

  當我看到這段代碼時,我就思考一個問題。既然是將圖片移動了100%的寬度,爲何不直接給全部的雪碧圖,設定一個統一的動畫,backgroun-position直接結束值爲background-position: 100% 0;,這樣就直接一步到位,還不用去計算每一個圖片的寬度。當我想出這個好方法,敲出簡潔的代碼,爲本身的聰明才智美滋滋的時候。運行結果直接呼了我一個大嘴巴子,總結起來總共有以下幾個問題:

  1)steps步數不對,按照官網的代碼copy下來,steps(8)根本實現不了效果;

  2)將steps(8)改寫成steps(7)時,人物確實是動起來了,可是在動畫結束時會卡幀;

  3)將steps(7)改寫爲steps(7,start)後,卡幀現象不明顯(只是不明顯了),但仔細觀察動畫,與實際效果仍不一致;

  

  出現問題後,我逐步解決了問題1和問題2,可是問題3,着實費了好大力氣才研究明白。接下來對問題3解決的講解,將是本文的重點,重點,重點!!!敲黑板!

  

重點:

  針對問題3的解決思路,必須明確兩點——background-position的計算方式;steps()函數的屬性值;

  background-position的計算方式,上邊已經說明。如今重點說一下steps()函數。

  steps()是針對幀數動畫,專有的函數,能夠說是沒有steps就沒有雪碧圖了。它主要有兩個函數值steps(number,start/end),第一個值number就是步數,理解起來也簡單,通常雪碧圖分爲幾張小圖,number就設定爲多少,幾張圖就走幾步。第二個值是固定的兩個值——start和end,這兩個值理解起來就稍微有點難度了。仍是舉例說明,簡單明瞭。

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>animation動畫練習</title>
 6     <style>
 7         div {
 8             width: 200px;
 9             height: 200px;
10             background: black;
11             -webkit-animation: move 1s steps(1,start) infinite;
12             -o-animation: move 1s steps(1,start) infinite;
13             animation: move 1s steps(1,start) infinite;
14         }
15         @keyframes move {
16             0% {
17                 background: red;
18             }
19             50% {
20                 background: yellow;
21             }
22             100% {
23                 background: blue;
24             }
25         }
26     </style>
27 </head>
28 <body>
29     <div></div>
30 </body>
31 </html>

 

  以上代碼,若是粘貼到編輯器中並運行,會發生一個有趣的現象。元素的背景顏色,將在yellow和blue間來回切換,至於元素自己的背景色black以及0%時的背景色red,都不會顯示。

  如今讓咱們把代碼中的steps的屬性值start改成end,再來看一下結果。此時,背景色在red和yellow間切換,black和blue將再也不顯示。

  咱們先不考慮元素自己背景色的顯示問題,這個相信不用說,你們也都明白。經過上面的例子,相信你們已經發現了其中的端倪——那就是start/end設置相應的屬性值時,動畫設定中的開始幀和結束幀就會跳過不顯示,這就是它們的做用。

 

  明白了step()函數的做用以後,讓咱們返回去再看一下剛纔出現的3個問題:

    1)steps步數不對,按照官網的代碼copy下來,steps(8)根本實現不了效果;

    這個主要是background-position按%百分比設置屬性值時,計算方式產生的影響。當我設置background-position: 100% 0;時,按照圖片總共分爲8張小圖片,每張小圖片寬度爲200px,背景寬度爲200px計算。實際上計算出來的位移值爲(200-1600)*100%=1400px,因此我實際的設置值爲background-position: -1400px 0;,結果一目瞭然,少走了一步,實際上只走了7張圖片的步數。因此steps值應改成steps(7);

    2)將steps(8)改寫成steps(7)時,人物確實是動起來了,可是在動畫結束時會卡幀;

    由於background-position: -1400px 0;,而steps第二屬性值start/end的默認屬性值是end,因此最後一張圖片並無顯示,銜接不上出現卡幀。

    3)將steps(7)改寫爲steps(7,start)後,卡幀現象不明顯(只是不明顯了),但仔細觀察動畫,與實際效果仍不一致;

    經過前兩步的解讀,到了這一步,其實很清晰了,設置成start後,輪到第一張沒顯示出來了。只是此次圖片間的銜接並不像第二步時,卡幀那麼明顯而已。

 

  那麼如今理解下來的話,問題3的重點就是2個問題:

    1)把少走的一步補回來;

    2)把steps函數沒有播放的那一幀補回來;

 

  第一個問題仍是回到background-position的計算問題上,既然設定100%時,是background-position: -1400px 0;走7步,那我設定多少才能是background-position: -1600px 0;走8步呢??這裏我倒推了一個公式——[100% / (圖片個數-1) + 100%],這樣算出來的百分比數,就是應該設定的數值,以此例計算的話就是——100% / (8-1) + 100% = 114.2857%。這樣計算下來的最終結果就是background-position: -1600px 0;,同時將steps(7,start)改成steps(8,start)。

  解決完第一個問題,再來解決第二個問題。設定了background-position: 114.2857% 0;以後,再看效果,發現不卡幀了。直接卡空白畫面了??Excuse me??這不是剛改完steps第一個屬性,還沒改第二個屬性值嘛。

  

  相信看完上面這張圖,你們內心確定是明明白白的了。修改完第一步以後,最後動畫停留的位置。其實是一片空白,由於圖片已經徹底溢出背景了。再來看steps的屬性值steps(8,start),設置了動畫第一幀不顯示,顯然是有問題了。那麼只須要將start刪除,讓steps匹配默認屬性end,按百分比設置的完美雪碧圖就完成了~

  

  到這裏,關於雪碧圖、background-position與steps函數三角戀情就八卦完畢了,若是還想看更多的CSS花邊新聞,敬請期待下一期CSS娛樂大搜查深刻淺出!歡迎批評指正!

相關文章
相關標籤/搜索