CSS動畫,2D和3D模組

  • 2019 年 10 月 11 日
  • 筆記

CSS3提供了豐富的動畫類屬性,使我們可以不通過flash甚至JavaScript,就能實現很多動態的效果。它們主要分為三大類:transform(變換),transition(過渡),animation(動畫)。其中transform又分為2D變換和3D變換,它賦予了我們不通過專業設計軟體製作平面或者立體圖形的能力。

 

一  過渡

 

  通過給元素設置transition屬性設置它的過渡效果。過渡實際定義的是元素從一種狀態變成另一種狀態的過程,比如寬度從100px變成300px,背景顏色從red變成orange等等。

 1 div{   2     width:200px;   3     height:200px;   4     background-color:red;   5     transition-property:width,background-color;   6     /*該屬性指定需要變換的元素屬性,不同屬性用逗號隔開*/   7     transition-duration:1s;   8     /*該屬性指定整個過程花費的時間,如需單獨為每個變化的屬性設置時間,請使用逗號隔開*/   9     transition-timing-function:ease;  10     /*該屬性設置變化的速度曲線,默認值即是ease,表示慢-快-慢,還有幾個其他的取值:linear,勻速;ease-in,慢-快,ease-out,快-慢,ease-in-out,慢-快-慢,肉眼效果和ease相似*/  11     transition-delay:1s;  12     /*延遲時間*/  13 }  

  元素的屬性設置好以後,需要某些操作觸發了指定屬性的變化才能看到效果,必如:hover,或者JS事件。

  另外,transition實際是一個複合屬性,多個屬性過渡可以簡寫:

1 div{  2     width:200px;  3     height:200px;  4     transition:width 2s 1s,background-color 2s;  5     /*transition-property和transition-duration是必須的,另外兩個是可選的*/  6 }  7 div:hover{  8     width:400px  9 }

  當有多個屬性需要設置過渡,並且持續事件,速度曲線,延遲時間均相同時,你可以如下簡寫:

1 div{  2     /*some code*/  3     transform:all 2s;  4     /*所有發生變化的屬性都設置過渡效果*/  5 }

 

二  動畫

 

  動畫其實和過渡一樣,都是用來給元素設置動態效果的,不同的是,過渡需要人為的觸發才能被執行,而這裡將要講解的動畫不需要人為觸發。

  在給元素設置動畫之前,我們首先應該創建一個動畫效果,即開始是什麼狀態,結束是什麼樣的狀態。

1 @keyframes sport{/*sport是動畫的名稱,可以自定義*/  2     from{  3         width:200px;  4     }  5     to{  6         width:400px;  7     }  8 /*除了使用from...to的方式,你還可以使用百分比創建更加豐富的動畫過程,0%表示開始時,100%表示結束時*/  9 }

  創建好動畫之後,你就可以為元素設置諸如動畫持續時長,速度曲線,重複次數等屬性了。

 1 div{   2     animation-name:sport;   3     /*規定元素需要執行的動畫名稱,即使用@keyframs創建的那個*/   4     animation-duration:5s;   5     /*規定動畫完成一個周期所花費的秒或毫秒*/   6     animation-timing-function:ease;   7     /*規定動畫的速度曲線,可選值同過渡*/   8     animation-delay:3s;   9     /*規定動畫延遲時間*/  10     animation-iteration-count:5;  11     /*規定動畫被播放的次數,infinite表示一直循環播放*/  12     animation-direction:alternate;  13     /*規定動畫是否在下一周期逆向地播放,normal是默認取值,表示不逆向播放,逆向播放一次也會在animation-iteration-count屬性值中減1*/  14     animation-play-state:paused;  15     /*規定動畫是否正在運行或暫停,默認值是running,表示正在運行*/  16     animation-fill-mode:forwards;  17     /*規定動畫結束後元素的狀態,forwards,保持動畫停止時的狀態,backwards,回到開始時的狀態,none,保持默認。一般沒有指定該屬性時,動畫結束後會回到開始時的狀態。不同瀏覽器可能有不同表現*/  18 }

 

三  2D變換

 

  通過給元素設置transform屬性,可以對元素進行2D變換。很多地方把transform翻譯成轉換,該單詞在英語中的含義是使改變,使變形。我更傾向於把它翻譯成變換,通過CSS變換,我們可以對元素進行移動、縮放、轉動、拉伸等操作。

 

  1,translate(x,y) 

1 div{  2     transform:translate(50px,100px);  3 }  4 /*div在水平方向移動50px,垂直方向移動100px*/

  translate方法接收兩個參數,分別表示在水平和垂直正方向上的偏移量,可以接收負值,表示向反方向偏移。

 

  2,rotate(deg)

1 div{  2     transform:rotate(30deg);  3 }  4 /*順時針方向旋轉元素30度*/

  rotate方法接收一個參數,表示元素旋轉的角度,可以接收負值,表示逆時針方向旋轉。rotate方法實際是通過修改元素的坐標系來達到旋轉元素的目的,比如:

1 div{  2     transform:rotate(45deg) translate(50px,0);  3     /*多屬性複合形式寫法*/  4 }  5 /*元素先旋轉45度,然後向瀏覽器x軸正方向偏下45度的方向移動50px*/

  默認情況下,元素都是以自己的中心點為圓心旋轉,我們可以通過transform-origin屬性修改該參考點。

1 div{  2     width:200px;  3     height:200px;  4     transform:rotate(30deg);  5     transform-origin:0px 0px;/*以左上角為圓點旋轉*/  6     /*取值200px 0px即以右上角為圓點旋轉。改屬性取值也可以是百分比或關鍵字。top,botton,left,right,center*/  7 }

  

  3,scale(x,y)

1 div{  2     transform:scale(2,3);  3 }  4 /*元素寬度放大2倍,高度放大3倍*/

  scale方法接收兩個參數,分別表示元素寬高需要縮放的比例,如果參數介於0到1之間則表示縮小,如果小於0,實際效果相當於翻轉元素,感興趣的朋友可以自行測試,觀察效果。

  

  4,skew(x,y)

1 div{  2     transform:skew(30deg,30deg);  3 }  4 /*元素在水平和垂直方向均傾斜30度*/

  skew方法接收兩個參數,分別表示X軸和Y軸傾斜的角度,如果第二個參數為空,則默認為0,參數為負表示向相反方向傾斜。

 

四  3D變換

 

  要想使元素以3D效果呈現,你可以給元素的父元素添加transform-style屬性

1 .father{  2     transform-style:preserve-3d;  3 }  4 .son{  5     /*some code*/  6 }

  transform-style屬性的默認值是flat,即平面的意思。通過設置其值為preserve-3d即可讓子元素以3D模式呈現。

  事實上,我們是通過配合使用rotate方法,最終實現3D立體效果的。

  我們知道,在2D空間,坐標軸只有x和y兩根軸,而在3D空間,一共有x,y,z三根軸。我們上面講解的rotate方法實際上都是圍繞z軸在旋轉,這也是該方法的默認方式。另外,其實我們還可以通過rotateX(),rotateY(),改變元素默認的旋轉軸向。改變旋轉軸向配合perspective屬性使用效果更佳。

 1 .father{   2     perspective:500px;   3     /*perspective屬性取值是一般是一個像素值,設置後可以實現旋轉後元素近大遠小的效果*/   4 }   5 .son{   6     width:200px;   7     height:200px;   8     transform:rotateX(45deg);   9 }
10 /*注意,perspective屬性需要設置在旋轉元素的祖先元素上,通常我們把它設置在其父元素上。*/

  下面是兩個3D立方體的示例程式碼:

  HTML部分:

 1 <div class="D3">   2     <ul>   3         <li>1</li>   4         <li>2</li>   5         <li>3</li>   6         <li>4</li>   7         <li>5</li>   8         <li>6</li>   9     </ul>  10     <ul>  11         <li>1</li>  12         <li>2</li>  13         <li>3</li>  14         <li>4</li>  15         <li>5</li>  16         <li>6</li>  17     </ul>  18 </div>

  CSS部分:

 1 body{   2     background-color: #ccc;   3     perspective: 800px;   4 }   5 .D3{   6     width:550px;   7     height: 200px;   8     margin:100px auto;   9 }  10 @keyframes sport{  11     from{  12         transform: rotateX(0deg) rotateY(0deg);  13     }  14     to{  15         transform: rotateX(360deg) rotateY(360deg);  16     }  17 }  18 .D3 ul{  19     width: 200px;  20     height: 200px;  21     position: relative;  22     transform-style: preserve-3d;  23     transform: rotateX(0deg) rotateY(0deg);  24     animation: sport 10s linear infinite alternate;  25     display: inline-block;  26     margin-left:50px;  27 }  28 .D3 ul li{  29     list-style: none;  30     width:200px;  31     height: 200px;  32     position: absolute;  33     opacity: 0.3;  34     font-size: 100px;  35     line-height: 200px;  36     text-align: center;  37 }  38 .D3 ul li:nth-child(1){  39     background-color: red;  40     transform:translateZ(100px);  41 }  42 .D3 ul li:nth-child(2){  43     background-color: blue;  44     transform: rotateX(90deg) translateZ(100px);  45 }  46 .D3 ul li:nth-child(3){  47     background-color: yellow;  48     transform: rotateX(180deg) translateZ(100px);  49 }  50 .D3 ul li:nth-child(4){  51     background-color: pink;  52     transform: rotateX(270deg) translateZ(100px);  53 }  54 .D3 ul li:nth-child(5){  55     background-color: purple;  56     transform: rotateY(90deg) translateZ(-100px);  57 }  58 .D3 ul li:nth-child(6){  59     background-color: green;  60     transform: rotateY(90deg) translateZ(100px);  61 }  62 /*還記得嗎?rotate方法是通過改變坐標系來達到旋轉的目的哦!*/

 

五  transform對其他元素的影響

 

  1,提高顯示優先順序

  我們知道,在標準文檔流中,如果使用負的margin值可以使一個元素覆蓋在另一個元素上,正常情況下是寫在後面的元素覆蓋前面的。但是設置了transform屬性的元素會覆蓋其他元素。

 1 .top{   2     width: 100px;   3     height: 100px;   4     background-color: red;   5     transform: rotate(0deg);   6 }   7 .bottom{   8     width: 100px;   9     height: 100px;  10     background-color: blue;  11     margin-top:-50px;  12 }  13 /*紅色的會覆蓋藍色的div 50px*/

  

  2,改變fixed定位的相對對象

  通常情況下,使用了position:fixed;屬性的元素都會相對瀏覽器窗口定位,不受滾動條的影響。但是當我們給其父元素設置了transform屬性後,這一狀況被改變了。

 1 .father{   2     width: 500px;   3     height: 500px;   4     margin-left: 100px;   5     margin-top: 100px;   6     border: 1px solid #000;   7     transform: rotate(0deg);   8 }   9 .son{  10     position: fixed;  11     top: 50px;  12     left:50px;  13     width: 100px;  14     height: 100px;  15     background-color: red;  16 }  17 /*.son不再以瀏覽器窗口作為參考點,而是以其父元素.father作為按參考點了*/

  

  3,改變absolute定位元素的寬度

  以前,如果一個元素設置了絕對定位,並且寬度設置為100%,那麼該元素的實際寬度是第一個有定位屬性的祖先元素的寬度,沒有則是body的寬度。現在,如果第一個有定位屬性的祖先元素和絕對定位元素之間,有一個設置了transform屬性的元素,那麼絕對定位元素的寬度繼承鏈將在該transform祖先元素處被截斷,最終絕對定位的元素寬度將繼承自transform元素。

 1 .grand{   2     width: 500px;   3     height: 500px;   4     border: 1px solid #000;   5     position: absolute;   6 }   7 .father{   8     width: 100px;   9     height: 100px;  10     background-color: red;  11     transform:rotate(0deg);  12 }  13 .son{  14     width: 100%;  15     height: 200px;  16     position: absolute;  17     background-color: yellow;  18 }  19 /*.son的寬度不是500px,而變成了100px*/

  

  寫在最後,transform是CSS3才引入的屬性,不同瀏覽器對它的實現也可能有差異,上面介紹的內容並不能保證在所有瀏覽器上均有相同的表現,具體情況請大家自行測試(我僅在Chrome 76測試)。