動畫(animations)

新式的CSS3中就已經有包含動畫的可定義值,內容相當的完整。CSS動畫指的是使用以CSS定義為主的動畫效果,又可以分成以下兩類:

轉場(Transition)

CSS 轉場允許您在給定的持續時間內平滑地更改屬性值。

將鼠標懸停在下面的紅色方塊上,查看轉場效果:

兩張圖片疊在一起,利用轉場方法,
將上面的圖片完全透明化,下面的圖片就展現出來。
將鼠標懸停在右邊的圖片上,查看轉場效果:

轉場用法

CSS 轉場允許您在給定的持續時間內平滑地更改屬性值。

要創建轉場效果,您必須指定兩件事:

以下示例顯示了一個 100px * 100px 的紅色 <div> 元件。 <div> 元件還為 width 屬性指定了轉場效果,持續時間為 2 秒:
<style>
div {
  width: 100px;
  height: 100px;
  background: red;
  transition: width 2s;
}

當指定的 CSS 屬性(寬度)更改值時,轉場效果將開始。

現在,當用戶將鼠標懸停在 <div> 元件上時,讓我們為 width 屬性指定一個新值:

<style>
div:hover {
  width: 500px;
}
</style>

CSS Transition

指定轉場的速度曲線

transition-timing-function 屬性指定了轉場效果的速度曲線。

transition-timing-function 屬性可以具有以下值:

延遲轉場效果

transition-delay 屬性指定轉場效果的延遲(以秒為單位)。

轉場+變形

以下示例為轉換添加了轉場效果:
div {
  transition: width 2s, height 2s, transform 2s;
}
以下示例為轉場添加了變形效果, 請將鼠標懸停在紅色方塊:

轉場+變形

CSS 3D

當要做 CSS 3D 的效果時,可以先假想兩層的元素。外層是視角,是用第三人稱的方向在看著內層;
內層就是物件的本身,可以有不同的 3D 屬性(旋轉、位移等等)。

HTML 結構如下:

<div class="perspective"> 
  <div class="flip-box"> 
  </div>
</div>

翻牌

在CSS 的屬性上,外層會提供 perspective 的透視屬性,這是從第三人稱看物件的距離,值可以先使用 500px ~ 1000px ; 在內層的屬性則必須包含 transform-style: preserve-3d,讓物件本身已 3D 的模式呈現,並加入 transform 的變形屬性,就可以完成基本的 CSS 3D 。

翻牌的基本CSS 結構如下:

.perspective {
  preserve: 500px;
}
.flip-box {
  transform-style: preserve-3d;
  transform: rotateY(180deg);
}

請將滑鼠懸停在牌上

cardback
13h

例題:翻牌

速記屬性轉場

CSS 轉場屬性可以一一指定,如下所示:
div {
  transition-property: width;
  transition-duration: 2s;
  transition-timing-function: linear;
  transition-delay: 1s;
}
或使用速記屬性轉換:
div {
  transition: width 2s linear 1s;
}
CSS 3D原理參考CSS 3D - 原理篇

CSS 動畫

CSS 允許在不使用 JavaScript 或 Flash 的情況下對 HTML 元件進行動畫處理!
要使用 CSS 動畫,首先必須為動畫指定一些關鍵影格(keyframes)。
關鍵影格保存元件在特定時間將具有的樣式。
Welcome to CSS animation! Welcome to CSS animation!

@keyframes 規則

當您在@keyframes 規則中指定 CSS 樣式時,動畫會在特定時間逐漸從當前樣式更改為新樣式。
要使動畫工作,您必須將動畫綁定到一個元件。

下例實現文本的水平滾動,達到走馬燈的效果:

<style>
div.animate {
  animation-name: example;
  animation-duration: 12s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}

@keyframes example {
  from {transform:translatex(-100%);}
  to {transform:translatex(100%);}
}
</style>
<div id="animate" style="font-size:3vw">Welcome to CSS animation! Welcome to CSS animation!</div>

下面的示例將“example”動畫綁定到 <div> 元件。 動畫將持續 4 秒,它會逐漸將 <div> 元件的背景顏色從“紅色”更改為“黃色”:

看效果

@keyframes 也可以設定幾個影格,如下所示:

@keyframes xmp {
  0% {transform:translate(0,0); }
  50% {transform:translate(200px,200px);}
  75% {transform:translate(200px,0px);}
  100% {transform:translate(0px,0px);}
}

CSS 動畫屬性總覽 ( CSS Animation Properties )

CSS 動畫共有八種屬性和一個八種屬性集合的簡短屬性縮寫。
屬性 說明
animation-name 動畫名稱
animation-duration 動畫持續時間,預設 0,單位 s 或 ms。
animation-delay 動畫延遲播放時間,預設 0,單位 s 或 ms。
animati1on-iteration-count 動畫播放次數,預設 1。 其他還有 infinite
animation-timing-function 動畫加速度函式,預設 ease。 其他還有: linear、ease-in、ease-out、ease-in-out step-start、step-end、steps(int,start/end)、cubic-bezier(n,n,n,n)。
animation-direction 動畫播放方向,預設 normal。其他還有 reverse、alternate、alternate-reverse。
animation-fill-mode 動畫播放前後模式,預設 none。 其他還有 forwards、backwards、both。
animation-play-state 動畫播放或暫停狀態,預設 running。 其他還有 paused。
這八種屬性,亦可透過 animation 的屬性,做簡短的縮寫,用法如下:
animation:name duration | timing-function | delay | iteration-count | direction | fill-mode | play-state;
動畫速記屬性示例
下面的示例使用六個動畫屬性:
div {
  animation-name: example;
  animation-duration: 5s;
  animation-timing-function: linear;
  animation-delay: 2s;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}
使用速記動畫屬性可以實現與上面相同的動畫效果:
div {
  animation: example 5s linear 2s infinite alternate;
}

旋轉的立方塊,詳細解說請見變形(transform) 3D基本使用
例題: 旋轉的立方塊

彈跳

假設沒有設定animation-timing-function情況下,動畫設定為 ease。 這意味著動畫開始緩慢,中間加速,然後緩慢結束。 這對於彈跳球來說並不理想。 可以使用三次貝塞爾曲線(cubic-bezier)來指定自定義動畫時間。
cubic-bezier 曲線的參數設定,可以參考使用圓球彈跳網站來計時動畫。 這些數字創建了一條曲線(慢、慢、慢、快)——這就是能夠創建彈跳效果的方式。
.ball {
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: radial-gradient
      (circle at 50px 50px, #5cabff, #000);

  animation: bounce 0.5s;
  animation-direction: alternate;
  animation-timing-function:
      cubic-bezier(.5,0.05,1,.5);
  animation-iteration-count: infinite;
}

@keyframes bounce {
  from { transform: translate3d(0, 0, 0);     }
  to   { transform: translate3d(0, 300px, 0); }
}
  
例題: 圓球彈跳
參考資料:bouncing-ball

使用 sprite 的動畫

圖像精靈(sprite)是圖像集合併成單一圖像。如下圖:

以戴帽人為例,使用以下屬性呈現動畫:

animation: <name> <duration of one frame in seconds> steps(<number of frames>) 
    動畫:<名稱> <一影格的持續時間(以秒為單位)> 步驟(<影格數>)<完成動畫的持續時間>。
    

先量得精靈圖的大小為 1472x325px,有八個影格,則單一影格大小為 184x325px。
在樣式表中,為 @keyframes 設定取圖範圍 ,即精靈圖寬度 0 到 1472px。
接著在 capguy 類別中,設定單一影格大小、背景圖片(即精靈圖)的 url,以及動畫屬性。
記得要頁面標明呈現動畫的區塊: <div class="capguy"></div>

如下所示:動畫名為walk、單格停留 1 秒、有 8 步(8格)和動畫無限持續。

<style>
@keyframes walk {
    from { background-position: 0px; }
    to { background-position: -1472px; }
}                         /* 精靈圖寬度*/

.capguy {
    width: 184px; height: 325px;  /* 單一影格大小*/
    background-image: url("../css/gif/capguy-walk-1472.png");  /* sprite 圖片位址*/
    margin: 0 auto;   /* 表示上下邊界為0 ,左右為 auto 表示自動均分。*/
    animation: walk 1s steps(8) infinite;  /* 動畫屬性*/
}
</style>
<div class="capguy"></div>

現在將以上代碼放置在希望播放動畫的頁面中就成功了。

例題: 戴帽人立定走
參考資料:animate-sprites-in-css 如要平移,必須在樣式表中加入平移的關鍵影格如下:

@keyframes move_forward	{
	0%{transform:translateX(-736px);}
	100%{transform:translateX(736px);}
	}
    

並將 move_forward 類別加入 capguy 的 animation 屬性,注意要用逗號隔開如下:

    animation: walk 1s steps(8) infinite, move_forward 8s linear infinite;
    

例題: 戴帽人行走

將 capguy 替換為 boy,設定背景圖片url,更改單一影格大小,以及動畫屬性,又是另一動畫!

例題: 兒童行走

熊貓走路
下例熊貓在山間走路,在動畫中加上背景圖片、步道和背景音樂(單擊畫面),使頁面更豐富。詳細解說見參考資料。

例題: 熊貓走路
參考資料:panda Animation

騎馬奔駛

有的精靈圖(如騎馬奔駛圖)各影格位置不易計算,可先用sprite-cutter切割為個別影格。
如騎馬奔駛圖切成16片,@keyframes 設定 16 段,每段佔 6.25%。
注意 animation-timing-function 設定為 step-start,動畫開始立即呈現第一個影格。

 <style>
  #horse {
    width:186px;
    height:141px;
    position:absolute;
    animation: oxxo 1s infinite step-start ;
  }

@keyframes oxxo{
    0%{
    background-image:url("tile000.jpg");
    }
    6.25%{
    background-image:url("tile001.jpg");
    }
      ... 依此類推,每格相間 6.25%
    100%{
    background-image:url("tile000.jpg");
    }
}
  </style>
  <div id="horse"></div>
  

例題: 騎馬奔駛
參考資料:css-animation

賽馬
原圖在:shawnmcburnie

網格圖像的 css 動畫

對於這個大小為 450px × 112px 的圖像,精靈幀大小為 112.5px X 112px,我們需要水平移動 4 幀,垂直移動 2 幀。
這意味著我們需要創建兩個單獨的 @keyframe 動畫來遍歷每個方向。 當 X 方向動畫正在播放時,Y 必須凍結直到它完成。
除非 X 動畫完成,否則不得觸發 Y 動畫。 這可以通過我證明 Y 動畫的動畫時間增加 4倍來完成。

     div.leopard{
      width: 112.5px;
      height: 56px;
      margin: 0 auto;
      background-image: url("../css/gif/leopard.png");
      animation: playX 1s steps(4) infinite,
                 playY 4s steps(2) infinite,
                 move_forward 12s linear infinite;
    }
    @keyframes playX {
      from {background-position-x: 0px;}
      to {background-position-x: -450px;}
    }
    @keyframes playY {
      from {background-position-y: 0px;}
      to {background-position-y: -112px;
      }
    @keyframes move_forward	{
		0%{transform:translateX(0px);}
		100%{transform:translateX(450px);}
	 }
    }
 

例題: Leopard
參考資料:css-animations-using-with-spritesheets-in-a-grid-image

水波效果的動畫

這個水波效果的原理其實就是用六個 div 疊在一起,接著最重要的就是將背景設為固定:background-attachment:fixed;,然後讓背景的尺寸有大有小, 就可以完成了,只要把六個 div 疊在一起,搭配 CSS 的 animation,就可以讓六個 div 依序出現。

因為位置都使用了絕對位置 ( absolute ),因此我們要將所有的 div 定位在圓心一定有難度,這時候就必須使用 CSS3 的好用工具:calc, calc可以自動計算位置,藉由這個方式,我們直接可以讓 CSS 替我們計算出圓心,相當的方便。( 注意!calc 的 + 、 - 號前後必須有空格,不然會出錯 ), 然後就是每個 animation 要逐一加上延遲時間,就可以逐一地冒出來,如果我們再把半徑設大一點,就會變成圓形或是橢圓形囉!

例題: 水波效果
參考資料:css-water-wave


原圖在:davidkpiano

DOM 動畫

創建動畫容器

使用一個簡單的網頁,含有容器元件。 所有動畫元件都應該與該容器元件相對。
<!DOCTYPE html>
<html>
<body>

<h1>My First JavaScript Animation</h1>

<div id ="container">
  <div id ="animate">動畫在此進行</div>
</div>

</body>
</html>

設計元件樣式

容器元件應使用 style = "position: relative" 創建。
動畫元件應使用 style = "position: absolute" 創建。
#container {
  width: 400px;
  height: 400px;
  position: relative;
  background: yellow;
}
#animate {
  width: 50px;
  height: 50px;
  position: absolute;
  background: red;
}

動畫程式碼

JavaScript 動畫是經由元件樣式進行編程來實現的。
這些更改由計時器調用。 當定時器間隔小時,動畫看起來是連續的。
id = setInterval(frame, 5);

function frame() {
  if (/* test for finished */) {
    clearInterval(id);
  } else {
    /* code to change the element style */
  }
}
例如:
function myMove() {
  let id = null;
  const elem = document.getElementById("animate");
  let pos = 0;
  clearInterval(id);
  id = setInterval(frame, 5);
  function frame() {
    if (pos == 350) {
      clearInterval(id);
    } else {
      pos++;
      elem.style.top = pos + "px";
      elem.style.left = pos + "px";
    }
  }
}

例題: animation.html

下雨效果

看圖來分析下,我們需要實現哪些效果。

  1. 雨滴下落效果,移動鼠標控制下落方向
  2. 雨滴下落散成小水珠,小水珠的移動方向和鼠標移動方向相同
  3. 雨滴下落到鼠標坐標一定範圍內,散成小水珠,同樣的,小水珠的移動方向也和鼠標移動方向相同

逐步詳細解說見canvas 實現漂亮的下雨效果

參考資料