【CSS】過渡、動畫和變換
1. 使用過渡
過渡效果一般是由瀏覽器直接改變元素的CSS屬性實現的。例如,如果使用:hover選擇器,一旦使用者將滑鼠懸停在元素之上,瀏覽器就會套用跟選擇器關聯的屬性。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Example</title> <style type="text/css"> p { padding: 5px; border: medium double black; background-color: lightgray; font-family: sans-serif;} #banana { font-size: large; border: medium solid green;} #banana:hover { font-size: x-large; border: medium solid white; background-color: #1fa6e6; color: white; padding: 4px;} </style> </head> <body> <p> There are lots of different kinds of fruit - there are over 500 varieties of <span id="banana">banana</span> alone. By the time we add the countless types of apples, oranges, and other well-know fruit, we are faced with thousands of choices. </p> </div> </body> </html>
當使用者將滑鼠懸停在span元素上的時候,瀏覽器就會回應,直接套用新的屬性。變化如下圖所示:
CCS過渡屬性允許控制應用新屬性值的速度。例如可以選擇逐漸改變範例中span元素的外觀,讓滑鼠移到單字banana上的效果更和諧。
transition-delay 和 transition-duration 屬性指定為CSS時間,是一個數字,單位為ms(毫秒)或s(秒)。
transition簡寫屬性的格式如下:
transition: <transition-property> <transition-duration> <transition-timing-function> <transition-delay>
修改前面範例的CSS程式碼如下:
p { padding: 5px; border: medium double black; background-color: lightgray; font-family: sans-serif;} #banana { font-size: large; border: medium solid green;} #banana:hover { font-size: x-large; border: medium solid white; background-color: #1fa6e6; color: white; padding: 4px; transition-delay: 100ms; transition-property: background-color,color,padding,font-size,border; transition-duration: 500ms; }
在這個例子中,為樣式添加了過渡,是透過#banana:hover 選擇器應用的。過渡會在使用者將滑鼠停留在span元素上100ms之後開始,持續時間為500ms,過渡應用到 background-color、color、padding、font-size和border屬性。下面的效果圖顯示了這個過渡的漸進過程:
注意這個範例中指定多個屬性的方式。過渡屬性的值用逗號隔開,這樣過渡效果才會同時出現。可以為延遲時間和持續時間指定多個值,它代表的意思是不同的屬性在不同的時間點開始過渡,且持續時間也不同。
1.1 建立反向過渡
過渡只有在套用與其關聯的樣式時才會生效。範例樣式中使用了:hover 選擇器,這表示只有使用者將滑鼠停留在span元素上才會套用樣式。使用者一旦將滑鼠從span元素上已開,只剩下#banana樣式,預設情況下,元素的外觀會立刻回到初始狀態。
因為這個原因,大多數過渡成對出現:暫時狀態的過渡和方向相反的反向過渡。修改前面範例的CCS程式碼,從而展示如何透過應用另一個過渡樣式平滑地傳回初始樣式。
p { padding: 5px; border: medium double black; background-color: lightgray; font-family: sans-serif;} #banana { font-size: large; border: medium solid green; transition-delay: 100ms; transition-duration: 500ms;} #banana:hover { font-size: x-large; border: medium solid white; background-color: #1fa6e6; color: white; padding: 4px; transition-delay: 100ms; transition-property: background-color,color,padding,font-size,border; transition-duration: 500ms; }
1.2 選擇中間值的計算方式
使用過渡時,瀏覽器需要為每個屬性計算初始值和最終值之間的中間值。使用transition-timing-function 屬性指定計算中間值的方式,表示為四個點控制的三次貝塞爾曲線。有五種預設曲線可以選擇,由下面的值表示:
* ease(預設值)
* linear
* ease-in
* ease-out
* ease-in
* ease-out
* ease-in-outout下圖可以看到這五種曲線,它們顯示了中間值隨著時間的推移變為最終值的速率。
搞清楚這些數值最簡單的辦法就是在自己的HTML文件中試驗。還有另一個值 cubic-bezier,可用來指定自訂曲線。 修改前面範例的CSS樣式如下,顯示 transition-timing-function 屬性的應用:p { padding: 5px; border: medium double black; background-color: lightgray; font-family: sans-serif;} #banana { font-size: large; border: medium solid green; transition-delay: 10ms; transition-duration: 250ms;; } #banana:hover { font-size: x-large; border: medium solid white; background-color: #1fa6e6; color: white; padding: 4px; transition-delay: 100ms; transition-property: background-color,color,padding,font-size,border; transition-duration: 500ms; transition-timing-function: linear; }
CSS動畫本質上是增強的過渡。在如何從一種樣式轉換到另一種樣式的過程中,具有了更多選擇、更多控制,以及更多彈性。
animation 簡寫屬性的格式如下:🎜animation: <animation-name> <animation-duration> <animation-timing-function> <animation-delay> <animation-iteration-count>
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Example</title> <style type="text/css"> #ball{ width: 180px; height: 180px; background-color:green; margin:20px auto;border-radius: 90px; -webkit-animation-delay: 100ms; -webkit-animation-duration: 2000ms; -webkit-animation-iteration-count: infinite; -webkit-animation-timing-function: linear; -webkit-animation-name:'GrowQuare'; } @-webkit-keyframes GrowQuare { to { background-color: yellow; border-radius: 0; } } </style> </head> <body> <div id="ball"></div> </body> </html>
要明白在这个示例中做了什么,应该仔细研究一下动画的两部分。第一部分是在样式中定义动画属性,是跟#ball选择器一起的。先看看基本属性:选择器样式应用100ms后开始播放动画属性,持续时间2000ms,无限重复播放,中间值使用linear函数计算。除了重复播放动画,这些属性在过渡中都有对应属性。
这些基本的属性并没有指出为哪些CSS属性应用动画。为此,要使用 animation-name 属性给动画属性起个名字,这里叫 GrowsQuare 。这样,就相当于告诉浏览器找一组名为 GrowQuare 的关键帧,然后将这些基本属性的值应用到 @keyframes指定的动画属性上。下面是此例代码中关键帧的声明(这里省略了-webkit前缀):
@-webkit-keyframes GrowQuare { to { background-color: yellow; border-radius: 0; } }
声明的开始是@keyframes,接着指定了这组关键帧的名字 GrowQuare。声明内部指定了一组要应用的动画效果。to 声明定义了一组设置动画样式的属性,同时也定义了动画结束时这些属性的最终值。动画的初始值来自进行动画处理的元素在应用样式之前的属性值。
此例的效果是一个大小为180像素的圆形,渐变成正方形。其显示效果如下图所示:
2.1 使用关键帧
CSS动画的关键帧机器灵活,非常值得研究。
(1) 设置初始状态
在前面的示例中,要处理为动画的属性的初始值来自元素自身。可以使用from子句指定另一组值。修改前面示例的CSS文件如下:
#ball{ width: 180px; height: 180px; background-color:green; margin:20px auto;border-radius: 90px; -webkit-animation-delay: 1000ms; -webkit-animation-duration: 2000ms; -webkit-animation-iteration-count: infinite; -webkit-animation-timing-function: linear; -webkit-animation-name:'GrowQuare'; } @-webkit-keyframes GrowQuare { from { background-color: black; width: 90px; height: 180px; border-radius: 45px/90px; } to { background-color: yellow; border-radius: 0; } }
在这个例子中修改了动画延迟为1000ms,并为背景色、宽度、高度、圆角边框属性提供了初始值,在to句子中指定的其他属性在动画开始时的初始值来自元素自身。从下面的显示效果可以看出来。最开始是一个绿色的圆形,然后一秒后直接变成一个竖立的黑色椭圆,再经过两秒逐渐改变成黄色的正方形。
(2) 指定中间关键帧
也可以添加其他关键帧定义动画的中间阶段。这是通过添加百分数子句实现的,修改前面示例CSS代码如下:
#ball{ width: 200px; height: 200px; background-color:green; margin:20px auto;border-radius: 100px; -webkit-animation-delay: 1000ms; -webkit-animation-duration: 2000ms; -webkit-animation-iteration-count: infinite; -webkit-animation-timing-function: linear; -webkit-animation-name:'GrowQuare'; } @-webkit-keyframes GrowQuare { from { background-color: black; width: 100px; height: 200px; border-radius: 50px/100px; } 50% { background-color: red; width: 50px;height: 100px; border-radius: 25px/50px;margin:70px auto; } 75%{ background: blue; width: 25px;height: 50px; border-radius: 12.5px/25px;margin:95px auto; } to { background-color: yellow; border-radius: 0; } }
对于每一个百分数子句,在动画中定义了一个点,这时子句中指定的属性和值会完全应用到样式上。此例中,定义了50%和75子句。
中关键帧有两个用途。一是为属性定义新的变化速率。浏览器会使用animation-timing-function 属性指定的调速函数计算由一个关键帧移动到下一个关键帧需要的中间值,以确保关键帧与关键帧之间流畅地播放。二则是定义属性值,以便创建更为复杂的动画。可以看到此例显示效果如下:
2.2 设置重复方向
动画结束后浏览器可以选择接下来动画以何种方式重复。使用 animation-direction属性指定首先方式。
修改前面示例CSS代码如下:
#ball{ width: 50px; height: 50px; background-color:green;border-radius: 25px; -webkit-animation-delay: 100ms; -webkit-animation-duration: 2s; -webkit-animation-iteration-count: 2; -webkit-animation-timing-function: linear; -webkit-animation-name:'GrowQuare'; -webkit-animation-direction: alternate; } @-webkit-keyframes GrowQuare { 50%{ margin-top: 200px; } to { margin-left:200px; } }
2.3 理解结束状态
CSS动画的一个局限是关键帧为属性定义的值只能在动画中应用。动画结束后,动画元素的外观回到初始状态。
2.4 初始布局时应用动画
跟过渡相比,动画的一个优势是可以将其应用到页面的初始布局。当把 animation-delay 属性的值设为0 (默认值),当页面一旦加载就会自动应用样式,这就意味着浏览器一旦显示HTML就有了动画效果。
PS:使用上诉方法要谨慎。如果要在页面中使用动画,而动画效果不是邀请用户只需某一动作,这种情况更应该慎之又慎。如果确实要使用动画,要保证动画效果缓和一些,不要妨碍用户阅读或者与页面其他部分交互。
2.5 重用关键帧
我们可以对同一组关键帧应用多个动画,从而动画属性配置不同的值。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Example</title> <style type="text/css"> #ball{ width: 50px; height: 50px; background-color:green;border-radius: 25px; -webkit-animation-delay: 100ms; -webkit-animation-duration: 2s; -webkit-animation-iteration-count: infinite; -webkit-animation-timing-function: linear; -webkit-animation-name:'GrowQuare'; -webkit-animation-direction: alternate; } #ball_second { width: 50px; height: 50px; background-color:green; -webkit-animation-delay: 100ms; -webkit-animation-duration: 2s; -webkit-animation-iteration-count: infinite; -webkit-animation-timing-function: linear; -webkit-animation-name:'GrowQuare'; -webkit-animation-direction: alternate; } @-webkit-keyframes GrowQuare { to { margin-left:200px; } } </style> </head> <body> <div id="ball"></div> <div id="ball_second"></div> </body> </html>
代码中展示了两个样式,它们都使用了GrowQuare 关键帧。效果图如下:
2.6 为多个元素应用多个动画
前面例子的一个变体是为多个元素应用同一个动画。在包含动画细节的样式中,扩展选择器的范围即可实现这一点。
(1)为多个元素应用一个动画
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Example</title> <style type="text/css"> #ball, #ball_second { width: 50px; height: 50px; background-color:green;border-radius: 25px; -webkit-animation-duration: 2s; -webkit-animation-iteration-count: infinite; -webkit-animation-timing-function: linear; -webkit-animation-name:'GrowQuare'; -webkit-animation-direction: alternate; } @-webkit-keyframes GrowQuare { to { margin-left:200px; } } </style> </head> <body> <div id="ball"></div> <div id="ball_second"></div> </body> </html>
(2)为一个元素应用多个关键帧
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Example</title> <style type="text/css"> #ball{ width: 50px; height: 50px; background-color:green;border-radius: 25px; -webkit-animation-delay: 500ms; -webkit-animation-duration: 2s; -webkit-animation-iteration-count: infinite; -webkit-animation-timing-function: linear; -webkit-animation-name:'Grow1','Grow2'; -webkit-animation-direction: alternate; } @-webkit-keyframes Grow1 { to { margin-left:200px; } } @-webkit-keyframes Grow2 { to { margin-top:200px; } } </style> </head> <body> <div id="ball"></div> </body> </html>
2.7 停止和启动动画
aniamation-play-state 属性可以用来停止和启动动画。如果这个属性的值为paused,动画就会停止。如果换成 playing。动画就会开始播放。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Example</title> <style type="text/css"> #ball { width: 50px; height: 50px; background-color:red;border-radius: 25px; -webkit-animation-delay: 500ms; -webkit-animation-duration: 5s; -webkit-animation-direction: alternate; -webkit-animation-iteration-count: infinite;; -webkit-animation-timing-function: linear; -webkit-animation-name:'GrowQuare'; } @-webkit-keyframes GrowQuare { to { width:200px; } } </style> </head> <body> <div id="ball"></div> <br /> <div> <button>Running</button> <button>Paused</button> </div> <script> var buttons = document.getElementsByTagName("button"); for(var i = 0; i < buttons.length; i++){ buttons[i].onclick = function(e){ document.getElementById("ball").style.webkitAnimationPlayState = e.target.innerHTML; } } </script> </body> </html>
3. 使用变换
我们可以使用CSS变换为元素应用线性变换,也就是说可以旋转、缩放、倾斜和平移某个元素。
3.1 应用变换
下面代码是一个变换的例子。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Example</title> <style type="text/css"> img{ border: medium double green; background-color: lightgray;} #banana2 { transform: rotate(-45deg) scaleX(1.2); } </style> </head> <body> <p> <img src="imgs/banana-small.png" alt="【CSS】過渡、動畫與變換" id="banana1"></p> <p> <img src="imgs/banana-small.png" alt="【CSS】過渡、動畫與變換" id="banana2"></p> </body> </html>
此例中,为#banana2 选择器添加了一个transform 属性声明,指定了两个变换。第一个是旋转-45°(即逆时针旋转45°);第二个是沿x轴进行因子为1.2的缩放。这些变换的效果如下图所示:
3.2 指定元素变换的起点
transform-origin属性允许我们指定应用变换的起点。默认情况下,使用元素的中心作为起点,不过,可以使用下表中的值选择其他起点。
要定义起点,需要为x轴和y轴各定义一个值。如果只提供一个值,另一个值会被认为是中心位置。下面代码展示了 transform-origin属性的用法。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Example</title> <style type="text/css"> img{ border: medium double green; background-color: lightgray;} #banana2 { transform: rotate(-45deg) scaleX(1.2); transform-origin: right top;} </style> </head> <body> <p> <img src="imgs/banana-small.png" alt="【CSS】過渡、動畫與變換" id="banana1"></p> <p> <img src="imgs/banana-small.png" alt="【CSS】過渡、動畫與變換" id="banana2"></p> </body> </html>
此例中,将变换的起点已到了元素的右上角,从下面的显示效果图可以看到:
3.3 将变换作为动画和过渡处理
我们可以为变换应用动画和过渡,就和其他CSS属性一样。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Example</title> <style type="text/css"> img{ border: medium double green; background-color: lightgray;} #banana2:hover { transform: rotate(360deg); transition-duration: 5s; } </style> </head> <body> <p> <img src="imgs/banana-small.png" alt="【CSS】過渡、動畫與變換" id="banana1"></p> <p> <img src="imgs/banana-small.png" alt="【CSS】過渡、動畫與變換" id="banana2"></p> </body> </html>
此例中,定义了一个过渡,它会经过5秒完成一次360°旋转变换。当用户将鼠标悬停在 #banana2 元素上,就会应用过渡,效果如下图所示: