共用方式為


如何讓畫布圖形產生動畫效果 (HTML)

[ 本文的目標對象是撰寫 Windows 執行階段 App 的 Windows 8.x 和 Windows Phone 8.x 開發人員。如果您正在開發適用於 Windows 10 的 App,請參閱 最新文件 ]

Canvas 元素是 HTML 文件上可以繪製的區域,您可以使用 JavaScript 產生圖形,像是動畫、圖表和遊戲。 這個主題說明使用 Canvas 元素製作基本繪圖動畫所需的步驟,幫助您開始使用。

先決條件

這個主題假設您:

  • 可以利用 JavaScript,以適用於 JavaScript 的 Windows Library 範本建立基本的 Windows 市集應用程式。
  • 具備 HTML 及 JavaScript 的基本知識。

如需使用 JavaScript 建立您的第一個 Windows 市集應用程式的指示,請參閱使用 JavaScript 建立您的第一個 Windows 市集應用程式。如需使用 WinJS 範本的指示,請參閱<如何取得和使用 WinJS 工具組>。

指示

步驟 1: 設定動畫計時

使用 requestAnimationFrame 方法,指定要針對下次重新繪製更新動畫時所呼叫的函式 (回呼) 來開始動畫:

requestAnimationFrame(animationFunction);

requestAnimationFrame 會考量頁面可見度及顯示器重新整理的頻率,判定每秒要為動畫配置幾個畫面 (也就是呼叫 animationFunction)。

我們的 JavaScript 範例會繪製以螺旋動作繞著較大圓形移動的動畫圓形。

requestAnimationFrame(draw);

以下是我們的動畫 (結果可能會有所不同,因為較快的硬體會產生間隔較為緊密的圓形):

畫布動畫所繪製的螺旋圓形範例。

步驟 2: 繪製影像

  1. 清除畫布

    您必須在繪製每個畫面之前清除畫布。

    您可以使用各種不同的方法清除畫布或部分影像,例如使用 globalCompositOperation 屬性清除特定區域,或使用 clip 方法裁剪路徑。 清除畫布最簡單的方法是使用 clearRect 方法。

    在我們的範例中,clearRect 方法是用來清除整個畫布,但是為了更容易看見繪製影像的效果,clearRect 方法已標記為註解。 如果這行程式碼未標記為註解,您就會看見以螺旋方式繞著較大圓形軌道移動的單一圓形,而且會在繪製每個畫面之前清除其軌跡。

    // The clearRect method clears the entire canvas.
    context.clearRect(0, 0, 160, 160);
    
  2. 儲存畫布狀態

    繪製影像時,您可能會變更一些設定,像是樣式或轉換。 如果您要在開始重新繪製每個影像時使用原始設定,可以使用 save 方法。

    saverestore 方法是用來儲存和抓取堆疊上的畫布狀態。 畫布狀態包含所有已套用的樣式和轉換。每次呼叫 save 方法時,目前的畫布狀態就會儲存到堆疊上。 restore 方法會從堆疊恢復最新的儲存狀態。

    我們的範例是在設定一些轉換來繪製和移動動畫圓形之前使用 save 方法。

    // Save the canvas state.
    context.save();
    
  3. 繪製影像

    將影像繪製到畫布上時,您可以使用兩種轉換來變更影像,一種是平移方法,另一種是旋轉方法。

    平移方法用來將畫布和其原點移到畫布格線中的不同點:

    translate(x, y)
    

    這種方法採用兩個引數:x 是畫布向左或向右移動的距離,y 是向上或向下移動的距離。

    在進行任何轉換之前儲存畫布狀態是比較好的做法,因為呼叫 restore 方法比執行反向平移更容易將畫布恢復為原始狀態。 translate 方法可讓您將影像放到畫布上的任何位置,而不必手動調整座標。

    rotate 方法是用來繞著目前原點旋轉畫布。 這個方法只有一個參數,也就是畫布旋轉的角度,以弧度為測量單位。

    rotate(angle)
    

    旋轉會順時針進行,旋轉中心點一律為畫布原點 (左上角)。 若要移動中心點,則需要使用 translate 方法移動畫布。

    在範例中,我們要替代幾個 translaterotate 方法呼叫。第一個 translate 方法呼叫會將動畫對齊畫布中央。

    接著我們要進行兩組 rotatetranslate 方法呼叫。 第一組呼叫 rotatetranslate 方法會產生繞著畫布以大迴圈繪製的小圓形。第二組呼叫則會產生以更小軌道繪製的小圓形。

    畫布大小設為高度 160 個像素,寬度 160 個像素,因此平移方法的 x 和 y 座標將設定為等於 80,使得整個動畫位在畫布的正中央。

    // centers the image on the canvas             
    context.translate(80, 80);
    

    我們使用 date 物件計算 rotate 方法的參數,開始第一次呼叫 rotate 方法。這個參數是畫布旋轉的角度。

    var time = new Date();
    context.rotate( ((2*Math.PI)/60)*time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds() );
    

    請注意,用來計算 getSeconds 的值是 60,而用來計算 getMilliseconds 的值是 60,000。

    translate 方法會移動 x 座標,這個座標會讓旋轉的圓形繞著畫布的大軌道移動。

    // Translate determines the size of the circle's orbit.
    context.translate(50, 0);
    

    這是第一組 rotatetranslate 方法的效果:

    沒有循環的大圓形。

    接下來的兩次 rotatetranslate 方法呼叫會建立較小的循環圓形軌道。

    // Rotate causes the circle to move in a small orbit.
    context.rotate( ((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds() );
    
    // Translate determines the size of the orbit.
    context.translate(0, 5);
    

    請注意,計算第二次旋轉呼叫的角度時,用來計算 getSeconds 的值是 6,而用來計算 getMilliseconds 的值是 6,000。

    如果第一組 rotatetranslate 方法在這裡標記為註解,則它會是第二組 rotatetranslate 方法繪製的內容:

    循環的圓形。

    所有重新定位都設定完成之後,圓形就會繪製到畫布上。

    // This draws the repositioned circle
    context.beginPath();
    context.arc(5, 5, 4, 0, Math.PI*2, true); 
    context.stroke();
    
  4. 還原畫布狀態

    之前我們已經在步驟 b 中儲存畫布狀態,那麼現在要重設畫布狀態,以便繪製下一個畫面。

    // Restores the canvas to the previous state
    context.restore();
    

完整範例

動畫圖形

這個 JavaScript 範例繪製以螺旋動作繞著較大圓形移動的動畫圓形。

window.onload = init;
  
// As an optimization, make "context" a global variable that is only set once.
var context;
  
function init(){
  context = document.getElementById('canvas').getContext('2d');    
  window.requestAnimationFrame(draw);
} // init

function draw() {
  // Save the canvas state.
  context.save();         
  
  // context.clearRect(0, 0, 160, 160);

  // centers the image on the canvas             
  context.translate(80, 80); 
  
  // Rotate moves the spiraling circle around the canvas in a large orbit.
  var time = new Date();
  context.rotate( ((2*Math.PI)/60)*time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds() );
  
  // Translate determines the location of the small circle.
  context.translate(50, 0);  
  
  // Rotate causes the circle to spiral as it circles around the canvas.
  context.rotate( ((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds() );
  
  // determines the size of the loop
  context.translate(0, 5);  
  
  // This draws the circle
  context.beginPath();
  context.arc(5, 5, 4, 0, Math.PI*2, true); 
  context.stroke();
  
  // Restores the canvas to the previous state
  context.restore();
  window.requestAnimationFrame(draw);
}  // draw

這是階層式樣式表 (CSS) 的範例,會在 Canvas 元素周圍建立黑色框線。

/* style the canvas element with a black border. */
canvas { border: 1px solid black; }

這個 HTML 檔案會建立 Canvas 元素並使用外部的 JavaScript 及 CSS 檔案。

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" src="myJavascript.js"></script>
        <link Rel="stylesheet" Href="myStyle.css" Type="text/css">
    </head>
    <body>
        <canvas id="canvas" width="160" height="160" />
    </body>
</html>

相關主題

快速入門:繪製至畫布