2011年2月9日 星期三

[CSS3 Minefield] Animation

上次寫過CSS3 Transition這次就寫一下CSS3 Animation-比Transition複雜但可以做出精細特效的終極神器。 (尤其是你要的屬性變更是非線性或不連續的時候)

[前言]
和CSS3 Transition一樣的是,本文只適用於webkit系的Chrome和Safari。 [Browser Support]
本篇會比一篇更傾向解Spec-基本上只要有Flash/Shockwave底子原理不難懂,差的是動畫特性: 流程與機能等。
另外這次的排版也有點不一樣-方便為主,semantics不是不想理是Blogger的系統不給理...
Let's Start。

[正文]
CSS3 Animation和CSS3 Transition相似,分別是Transition非常自動(implicit)而Animation有較多手動可以控制的地方(explicit),可以做精細的特效。
最重要的是CSS3 Animation是有名制+Keyframe式的: 每組動畫都有自己的名字(animation-name),內有數個keyframe,作者只要指定Keyframe 的CSS屬性值 (properties value,每格keyframe可以改變數個屬性) 和時間函數 (timing-function,預設ease),然後再經CSS屬性把animation套到某個Element上那麼瀏覽器就會自動補完全部frame (當然包括屬性變更的過場了),形成動畫。
例:

I am moving
把滑鼠移到上面的紅色字內你會看到字左移右擺的 XD

CSS (精華版):
#text-move:hover {
-webkit-animation-name: text-move;
-webkit-animation-duration: 1s;
-webkit-animation-delay:0s;
-webkit-animation-fill-mode:both;
}
@-webkit-keyframes text-move {
  0% { text-indent:0; }
  40% { text-indent: 10em; }
  60% {text-indent: 5em; }
  100% {text-indent: 15em;}
}

HTML:
<p id="text-move"><span> I am moving </span></p>

HTML很簡單可是CSS很火星吧? 先從最火星的講起。(*因為Animation這模組仍是draft,實際在webkit上用需要vendor-prefix)

定義animation - keyframes rules: @keyframes/ @-webkit-keyframes
最重要的東西,這是定義整組動畫的規則 (規則 = Rule = {}),方式是 @-rule:
@-webkit-keyframes animation-name {
/* keyframes blocks */
  0% { ... }
  20% { ... }
  100% { ... }
}

*小心keyframes的s
animation-name 是動畫的名字,之後會用到;keyframes blocks就是這個動畫的內容-keyframes的CSS,定義方式如下:

定義keyframes - keyframes blocks: 0-100%
看見上面那些 0% { ... }、 100% {...} 的東西嗎? 這些就是keyframe的主體、定義keyframe的block們。上面的百分比是時間selector,0%是開始、100%是完結,一個block可以套在多於一個時間上(逗號分隔):
0%, 20%, 40% { ... }
(這樣子0-40%會是同一個frame維持不動)

而block的內容和一般的CSS block一樣:
20% { color: red; font-size: 20px;  }
40% { color: blue; font-size: 40px; }

絕大多數常用的CSS property都沒有問題,特別的是你可以指定animation-timing-function決定目前這個keyframe下一個keyframe中間frame-to-frame的數值變化:
0% {
  left: 20px;
  webkit-animation-timing-function: linear;
 }
10% { left: 40px; }

(這樣子 0% - 10%會是均速移動)
* 100%因為沒有下一格了所以animation-timing-function會被無視
{注意事項} Spec寫某些frame 可以省略,不過實際上是甚麼也可以省 0% 和 100% 就是不能省...

套用animation - CSS property: animation-name/ -webkit-animation-name
定義好animation之後就可以套在某個Element上,方法是用animation-name (-webkit-animation-name) 叫出之前定義好的animation (value用animation-name) + 用animation-duration (-webkit-animation-duration)決定動畫長度  :
selector {
-webkit-animation-name: animation-name;
-webkit-animation-duration: time;
}

用一開始的例子來說animation-name應該是"text-move";時間可以用s或ms定義,e.g. 1s, 2000ms
而name本身可以有多於一個 (用逗號分隔),各自可以指定不同的duration、delay、fill-mode等屬性(逗號分隔,一對一,和transition一樣):
#box {
-webkit-animation-name: fly, shake;
-webkit-animation-duration: 1s, 2s;
-webkit-animation-delay: 0s, 1s;
...
}

這樣'fly'和'shake'會同時套用(apply)至#box,在頁面load完的剎那 (詳解見animation-delay)
至於selector則是一般合法的CSS selector:  :hover、attribute selector一樣可用,如果用的是:hover或:target或者不是hardcode了的class可以把animation改成由event觸發apply

[ ! ] 另外還有好幾個CSS屬性可以決定這個animation的行為 (prefix自己去補):
animation-delay
[時間] Animation實際有三個階段: apply (套用), execute (執行), end (完結)
這個屬性是在apply和excute之間加入一個緩衝時間(預設是0)。至於為什麼要這個緩衝是因為整個頁面全部animation是容許同步apply (i.e. sync),也就是說如果animation是套在id或element selector等一load完馬上trigger的CSS selector上,在預設delay為0之下不管多少個不同的element的animation也是全部同時執行...
(這在慢的機器上是會卡的-就可以同步而言webkit是太威了...)
*spec寫這個時間可以是負數-如果是負數會剪掉由0至delay時間的所有frame...
[正常][負delay: 一開始即飛至後半]

animation-iteration-count
[infinite | 數字] 動畫的重覆(loop)次數,指定infinite會一直重覆,指定數字則是重覆次數。預設是 1
(i.e. 所有animation預設只執行一次,不重覆)

animation-fill-mode
[none | forwards | backwards | both] 其中一個非常重要的屬性,但Safari 5和iOS 4.0之後才支援。需要這個屬性的原因是因為在預設行為'none'之下animation所做過的任何改變皆會被還原至animation發生前的狀態: 不是0%也不是100%
(I) 對0%來說,delay時並非0%那格的狀態
(II) 對100%來說,完結時會還原至animation開始前的狀態
(II)對於很多情況來說是十分差的狀態,還好SMIL有遇過這種麻煩事情所以Apple祭出了fill-mode解決這個囧境:
none: 預設行為
forwards: 解決II - 將元素定格在100%的狀態 (滾前)
backwards: 解決I - 在套用animation的一刻將元素更動為0%的狀態,一直hold至delay完畢 (滾後)
both: forwards + backwards = 以上兩者皆是


animation-timing-function
[webkit: ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier()] 整個animation的timing-function,會被keyframes的同名屬性override-當作是全部keyframes的預設值吧 (如果沒解錯spec...)
*w3c是有多點function,不過safari 沒有implementation,要用cubic-bezier()

animation-direction
[normal | alternative] 如果iteration-count > 1,用alternative時單數正向播放但雙數會是逆向。預設是normal
(這個是用來收尾用的多...)

animation-play-state
[running | paused] js programming用的屬性,去中斷(paused)一個animation的播放及恢復播放(running,等同resume)

[Full Reference] [W3C Spec]

[小提示]
1. Restart一個animation的方法是去改變他的animation-name: 先set empty string再set名 [stackoverflow]
2. shorthand和簡寫沒提是因為那些部分有雷...總之別懶
3. 如果animation之間存在沖突會是leftmost(最左手邊的那個)主導。

[小結]
Spec只有14頁,不過好些特性要做過才知道其用處-不過還好是因為Apple的人寫的,Spec本身還算易明,要反覆驗證的地方不多,祝玩的愉快~

[Appendix: 已知可以改變的CSS屬性一覽]
background-color
border-right-width
letter-spacing
padding-left
background-position
border-top-width
margin-left
right
border-left-color
font-weight
outline-offset
color
min-width
max-height
top
width
background-image (gradients)
border-spacing
line-height
padding-right
border-bottom-width
border-width
margin-right
text-indent
border-left-width
height
outline-width
crop
opacity
max-width
vertical-align
word-spacing
background-position
border-top-color
margin-bottom
padding-top
border-color
bottom
margin-top
text-shadow
border-right-color
left
padding-bottom
font-size
outline-color
min-height
visibility
z-index


[Source: Hardboiled Web Design , CSS3 keyframe animations]

=====Magic Area=====



[Magic occur without :target]

2 則留言: