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測試)。