如何对画布图形进行动画处理 (HTML)
[ 本文适用于编写 Windows 运行时应用的 Windows 8.x 和 Windows Phone 8.x 开发人员。如果你要针对 Windows 10 进行开发,请参阅 最新文档 ]
canvas 元素是 HTML 文档的可绘制区域,可以使用 JavaScript 收集图形(如动画、图表和游戏)。 本主题首先介绍使用 canvas 元素对基本图形进行动画处理所需的步骤。
先决条件
本主题假设你:
- 可以创建使用 JavaScript 的基本 Windows 应用商店应用,该应用使用 Windows JavaScript 库模板。
- 对 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 和 rotate 方法。
translate 方法用于将画布及其原点移动到画布网格中的另一点:
translate(x, y)
此方法采用两个参数:x 是画布的左移或右移量,y 是画布的上移或下移量。
在执行任何转换之前,最好保存画布状态,因为与为了使画布返回到其原始状态而必须执行反向转换相比,调用
restore
方法会更方便。translate
方法允许你将图像放置在画布上的任何位置,而不必手动调整坐标。rotate
方法用于围绕当前的原点旋转画布。 此方法只有一个参数:画布的旋转角度(以弧度作为度量单位)。rotate(angle)
旋转是顺时针移动,旋转中心始终为画布的原点(左上角)。 若要移动中心,需要使用
translate
方法移动画布。在我们的示例中,我们将对
translate
和rotate
方法交替调用几次。对translate
方法的第一次调用会将动画放在画布中央。接着,我们将对
rotate
和translate
方法进行两组调用。 对于rotate
和translate
方法的第一组调用将生成一个在画布周围沿着一个大环绘制的小圆。第二组调用将生成一个沿小得多的轨道绘制的小圆。画布的高度和宽度都设置为 160 像素,因此,我们会将 translate 方法的 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);
请注意,在为第二个 rotate 调用计算角度时,用于计算
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
这是在 canvas 元素周围创建黑色边框的级联样式表 (CSS) 的示例。
/* 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>