如何讓畫布圖形產生動畫效果 (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: 繪製影像
清除畫布
您必須在繪製每個畫面之前清除畫布。
您可以使用各種不同的方法清除畫布或部分影像,例如使用
globalCompositOperation
屬性清除特定區域,或使用clip
方法裁剪路徑。 清除畫布最簡單的方法是使用clearRect
方法。在我們的範例中,
clearRect
方法是用來清除整個畫布,但是為了更容易看見繪製影像的效果,clearRect
方法已標記為註解。 如果這行程式碼未標記為註解,您就會看見以螺旋方式繞著較大圓形軌道移動的單一圓形,而且會在繪製每個畫面之前清除其軌跡。// The clearRect method clears the entire canvas. context.clearRect(0, 0, 160, 160);
儲存畫布狀態
繪製影像時,您可能會變更一些設定,像是樣式或轉換。 如果您要在開始重新繪製每個影像時使用原始設定,可以使用
save
方法。save
和restore
方法是用來儲存和抓取堆疊上的畫布狀態。 畫布狀態包含所有已套用的樣式和轉換。每次呼叫save
方法時,目前的畫布狀態就會儲存到堆疊上。restore
方法會從堆疊恢復最新的儲存狀態。我們的範例是在設定一些轉換來繪製和移動動畫圓形之前使用
save
方法。// Save the canvas state. context.save();
繪製影像
將影像繪製到畫布上時,您可以使用兩種轉換來變更影像,一種是平移方法,另一種是旋轉方法。
平移方法用來將畫布和其原點移到畫布格線中的不同點:
translate(x, y)
這種方法採用兩個引數:x 是畫布向左或向右移動的距離,y 是向上或向下移動的距離。
在進行任何轉換之前儲存畫布狀態是比較好的做法,因為呼叫
restore
方法比執行反向平移更容易將畫布恢復為原始狀態。translate
方法可讓您將影像放到畫布上的任何位置,而不必手動調整座標。rotate
方法是用來繞著目前原點旋轉畫布。 這個方法只有一個參數,也就是畫布旋轉的角度,以弧度為測量單位。rotate(angle)
旋轉會順時針進行,旋轉中心點一律為畫布原點 (左上角)。 若要移動中心點,則需要使用
translate
方法移動畫布。在範例中,我們要替代幾個
translate
和rotate
方法呼叫。第一個translate
方法呼叫會將動畫對齊畫布中央。接著我們要進行兩組
rotate
和translate
方法呼叫。 第一組呼叫rotate
和translate
方法會產生繞著畫布以大迴圈繪製的小圓形。第二組呼叫則會產生以更小軌道繪製的小圓形。畫布大小設為高度 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);
這是第一組
rotate
和translate
方法的效果:接下來的兩次
rotate
和translate
方法呼叫會建立較小的循環圓形軌道。// 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。如果第一組
rotate
和translate
方法在這裡標記為註解,則它會是第二組rotate
和translate
方法繪製的內容:所有重新定位都設定完成之後,圓形就會繪製到畫布上。
// This draws the repositioned circle context.beginPath(); context.arc(5, 5, 4, 0, Math.PI*2, true); context.stroke();
還原畫布狀態
之前我們已經在步驟 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>