快速入门:绘制到画布 (HTML)

[ 本文适用于编写 Windows 运行时应用的 Windows 8.x 和 Windows Phone 8.x 开发人员。如果你要针对 Windows 10 进行开发,请参阅 最新文档 ]

canvas 元素在页面上生成一个矩形的位图画布,在该画布上,可以使用 JavaScript 实时绘制图形图像。画布非常适合创建游戏,还非常适合实时收集图形或定期更改图形的情形。

本快速入门包含以下部分:

  • 先决条件
  • canvas 元素
  • 呈现上下文
  • 绘制矩形
  • 使用路径
  • 绘制弧形
  • 绘制曲线
  • 二次曲线
  • 贝赛尔三次曲线
  • 后续步骤

先决条件

本主题假设你可以创建包含 Windows JavaScript 库模板且采用 JavaScript 的基本 Windows 应用商店风格应用,而且你对 HTML 和 JavaScript 有基本的了解。有关创建第一个采用 JavaScript 的 Windows 应用商店应用的说明,请参阅创建第一个 Web 应用。有关使用 WinJS 模板的说明,请参阅“如何获取和使用 WinJS 工具包”。

canvas 元素

canvas 元素在你的页面上生成一个矩形的位图画布,在该画布上,可以使用 JavaScript 实时呈现图形图像。

canvas 元素具有 width 和 height 属性。 这两个属性都是可选的,而且都可以使用文档对象模型 (DOM) 属性进行设置。 如果你未设置 width 和 height 属性,则画布会以其默认大小(width 和 height 分别为 300 个像素和 150 个像素)显示。

<canvas id="canvas" width="150" height="150"></canvas>

id 属性不属于 canvas 元素,但它可用于标识脚本中的 canvas 元素。

你可以使用级联样式表 (CSS) 设置画布的大小。默认情况下,你的应用呈现没有任何内容和边框的 canvas 元素(即完全透明的 canvas 元素)。但是,你可以像对任何普通图像那样,通过指定边距、边框、背景等来设置 canvas 元素的样式。设置样式不会影响画布上的实际绘制。

呈现上下文

向应用中添加 canvas 元素只是创建透明的绘制图面。若要绘制画布,需要从画布中获取呈现上下文并使用该上下文进行绘制。不同类型的呈现内容使你能够以不同的方式进行绘制。例如,2D 上下文用于 2D 图形,3D 上下文用于 3D 图形。本主题中的示例使用 2D 呈现上下文。

若要获取呈现上下文,请调用画布的 getContext 方法,如以下示例所示:

var canvas = document.getElementById("quickstart");
var context = canvas.getContext("2d");

在我们的示例中,首先使用 getElementById 检索画布的 DOM 节点,然后使用 getContext 方法访问呈现上下文。getContent 方法采用一个表示上下文类型的参数,在我们的示例中为“2d”。

在获取了呈现上下文之后,可以使用它进行绘制。接下来的几部分介绍如何绘制不同类型的形状。

绘制矩形

可以使用以下两个函数来在画布上绘制矩形:

  • fillRect

    fillRect (x, y, width, height)

    该方法绘制填充矩形。

    x, y 参数是用来在画布上对矩形进行定位的坐标,它们是相对于画布的左上角的。 width 和 height 是以像素度量的。

  • strokeRect

    strokeRect(x, y, width, height)

    strokeRect 的参数与 fillRect 的参数基本相同, 区别位于 strokeRect 仅绘制矩形的轮廓。

以下方法设置指定形状的颜色:

  • fillStyle

    fillStyle = color

    fillStyle 方法使用单个参数来用颜色填充形状。颜色可以使用 RGB、预定义的颜色(如红色、蓝色等)、十六进制颜色或者甚至渐变来设置。有关 fillStyle 示例,请参阅下面的“绘制矩形”示例。

以下方法清除指定的区域并使其完全透明:

  • clearRect

    clearRect(x, y, width, height)

    fillRectstrokeRect 与方法一样,clearRect 的 x 和 y 参数用来定位要清除的矩形区域,width 和 height 用来设置该矩形的宽度和高度。

示例

让我们从这样一个示例开始:创建一个画布,并绘制两个填充正方形(一个是金色正方形,一个是透明的紫色正方形)。我们将使用 CSS 在画布周围创建黑色边框:

两个填充的正方形。

该示例首先在 HTML 的 <body> 部分中声明一个 canvas 元素。为该 canvas 元素分配一个名为“canvas”的 id 属性,并将该元素的 height 和 width 属性设置为 100 个像素:

<body>
   <canvas id="canvas" width="100" height="100" />
</body>

该 canvas 元素是使用 CSS 创建的,它的宽度为 1 个像素,而且具有黑色实线边框。该 CSS 应当包含在一个外部文件中,以便尽可能提高文件加载效率:

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

我们的 JavaScript 代码在画布上绘制两个填充的矩形,它也包含在一个外部文件中。在加载 HTML 文档之后,它将使用 window.onload 事件处理程序调用 draw 函数。

window.onload = draw;

draw 方法使用 getElementById 方法获取 canvas 元素,然后调用 getContext 方法来获取绘制上下文。 你必须向 getContext 方法传递字符串“2d”。

每个画布都有一个绘制上下文。绘制上下文是指在其中定义所有绘制方法和属性的位置。

// Get the canvas element.
var canvas = document.getElementById("canvas");

// Specify a 2-D drawing context.
var context = canvas.getContext("2d");

若要开始绘制第一个正方形,请将 fillStyle 设置为一种颜色。可通过多种方式来填充矩形。我们的示例使用的是与金色等效的 RGB 颜色:

context.fillStyle = "rgb(255, 215, 0)";

下面是一些用来设置 fillStyle 的其他方法:

  • 使用预定义的颜色(如 "yellow"、"orange"、"purple" 等,但前提是它们可用):

    context.fillStyle = "gold";

  • 或者,使用 #RRGGBB 形式的十六进制颜色表示形式:

    context.fillStyle = "#FFD700";

    这个十六进制表示深金色。

  • 对于 fillStyle 可以使用渐变(尽管这不被视为颜色):

    var myGradient=context.createLinearGradient(20, 20, 100, 0);
    
    myGradient.addColorStop(0,"goldenrod");
    myGradient.addColorStop(1,"white");
    
    context.fillStyle = myGradient;
    

    以下示例创建一个线性渐变,设置颜色停止点,并导致用从金黄色到白色的颜色渐变来填充所绘制的矩形。

    两个填充的正方形。

  • 默认的 fillStyle 是实心黑色。

接着,我们将使用 fillRect 方法实际绘制矩形。fillRect 值首先绘制一个填充的矩形,方法是将该矩形左上角的 x 和 y 坐标设置为“15, 15”。x 和 y 坐标是相对于画布的左上角的。 矩形的宽度和高度分别设置为 55 和 50 像素:

context.fillRect (15, 15, 55, 50);

对于第二个矩形,fillStyle 设置为与紫色等效的 RGB:RGBA 中的第四个值“A”(表示 Alpha)设置为 0.5,用来确定颜色的不透明度。有效 Alpha 值的范围是从 0.0(完全透明)到 1.0(完全不透明):

context.fillStyle = "rgba(0, 0, 200, 0.5)"

fillRect 值首先在“40, 40”处绘制矩形左上角的 x 和 y 坐标。矩形的宽度和高度分别设置为 45 和 40 像素:

context.fillRect (40, 40, 45, 40);

下面是完整的代码示例:

下面是 JavaScript 代码。在我们的示例中,此文件将命名为 myJavascript.js:

window.onload = draw;   

// This function is called on page load.
function draw() {

    // Get the canvas element.
    var canvas = document.getElementById("canvas");

    // Specify a 2d drawing context.
    var context = canvas.getContext("2d");

    // Set the color to the RGB equivalent of gold.
    context.fillStyle = "rgb(255, 215, 0)";

    // Draw the rectangle.
    context.fillRect (15, 15, 55, 50);

    // Set the color to the RGB equivalent of purple and
    // set the opacity of the rectangle to 50 percent.
    
    context.fillStyle = "rgba(0, 0, 200, 0.5)"

    // Draw the rectangle.
    context.fillRect (40, 40, 45, 40);
}

下面是 HTML 文件:

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

使用路径

beginPath 方法启动一个新路径,然后使用其他方法(如 moveTolineToarc)绘制直线、曲线和其他形状的组合。

在创建路径之后,可以使用 fillStylestrokeStyle 方法将路径呈现到画布上。

示例

此示例将绘制一个棕色的三角形:

一个填充的三角形

此示例中使用的 HTML 和 CSS 文件与第一个示例中所使用的文件相同。 在我们的 myJavascript JavaScript 文件中,我们将使用与第一个示例中相同的 draw 函数,而且将在加载 HTML 之后再次调用该函数。

在获取 canvas 元素并指定 2D 画布类型之后,我们将通过调用 beginPath 方法来开始绘制棕色三角形。

context.beginPath();

在内部,路径存储为在一起构成形状的子路径(直线、弧等)的列表。每当调用 beginPath 方法时,该列表都会重置,我们都将开始绘制新形状。

在绘制任何直线之前,都将需要调用 moveTo 函数。 moveTo 函数不绘制任何内容,它类似于将钢笔或铅笔放在要开始绘制三角形的点。

context.moveTo(28, 20);

moveTo 采用两个参数:x 坐标和 y 坐标。 在这里,我们已将 x 坐标和 y 坐标分别设置为 28 和 20。这两个坐标相对于要在其上进行绘制的画布的边框。

现在,我们将使用 lineTo 函数绘制三角形的边。 与 moveTo 函数一样,lineTo 函数也包含两个参数(x 坐标和 y 坐标),这两个坐标相对于要绘制的直线的端点:

context.lineTo(78, 50); 
context.lineTo(28, 78); 
context.lineTo(28, 20); 

在我们的示例中,我们将 fillStyle 属性设置为表示棕色的十六进制值。 正如在“绘制矩形”部分中所讨论的那样,fillStyle 属性可以为 RGB、十六进制颜色、预定义颜色或者渐变。

context.fillStyle = "#996633";

我们将使用 fillStyle 绘制实心的棕色三角形。 我们可以使用仅绘制形状轮廓的 strokeStyle 函数。

现在,绘制三角形的轮廓。

context.fill();

下面是完整的 JavaScript 代码:

    // Get the canvas element.
    var canvas = document.getElementById("canvas");

    // Specify a 2-D canvas type.
    var context = canvas.getContext("2d");
           
    // Add the brown triangle.
    context.beginPath();
    context.moveTo(28, 20);
    context.lineTo(78, 50); 
    context.lineTo(28, 78); 
    context.lineTo(28, 20); 
          
    // Set the color to the hexadecimal equivalent of brown.
    // Omit this step and the triangle will render 
    // the default color of black.
    context.fillStyle = "#996633";

    // Draw the triangle.
    context.fill();  

绘制弧形

我们将使用 arc 方法绘制弧形或圆形:

context.arc(x, y, radius, startingAngle, endingAngle, antiClockwise);

此方法采用以下五个参数:

  • X 和 y 是圆心的坐标。
  • radius 是圆心距离圆上各点的距离。
  • startingAngle 和 endingAngle 参数以弧度定义弧的起点和终点(从 x 轴测量)。
  • anticlockwise 参数是一个布尔值,当它为 true 时,会沿着逆时针方向绘制弧,否则将沿着顺时针方向绘制。

示例

此示例将绘制一个蓝色的圆。

蓝色的圆

在获取 canvas 元素并指定 2D 画布类型之后,我们将通过调用 beginPath 方法来开始绘制圆。

context.beginPath();

在上面的矩形和三角形示例中,我们使用 fillStyle 函数对形状进行填充和着色。 在此示例中,我们将 RGB 颜色设置为蓝色,而且使用 strokeStyle 仅绘制圆形的轮廓。

// Define the stroke color in RGB for blue.
context.strokeStyle = "rgb(0, 162, 232)";

arc 函数按如下方式定义:

// Define the circle using an arc.
context.arc(50, 50, 32, 0, 2 * Math.PI, true);

其中:

  • x 和 y 坐标将圆心分别置于 50 和 50 处。
  • 圆的半径设置为 32。
  • 圆的起点和终点分别设置为 0 和 "2 * Math.PI" 弧度(表示这是一个整圆)。
  • anticlockwise 参数设置为 true,在绘制整圆时这不是非常重要,但在绘制圆形的一部分时这无疑非常重要。

最后,stroke 函数用来绘制我们刚才定义的圆。

// draw the circle.
context.stroke();

下面是在仅绘制圆形的一半(即从零绘制到 Math.PI)时的圆形外观:

// Define the circle using an arc.
context.arc(50, 50, 32, 0, Math.PI, true);

绘制了一半的圆。

下面是 JavaScript 代码。 此代码也是将包含在一个 draw 函数中,该函数将在加载 HTML 页面之后被调用。 有关完整的 HTML 或 JavaScript 文件示例,请参阅“绘制矩形”部分。

// Get the canvas element.
var canvas = document.getElementById("canvas");

// Specify a 2-D canvas type.
var context = canvas.getContext("2d");
          
// Start the path.
context.beginPath();

// Define the stroke color in RGB for blue.
context.strokeStyle = "rgb(0, 162, 232)";

// Define the circle using an arc.
context.arc(50, 50, 32, 0, 2 * Math.PI, true);

// draw the circle.
context.stroke();

绘制曲线

曲线用于绘制复杂的形状。 共有两种类型的曲线:贝赛尔或三次;以及quadratic。 这两种曲线在画布上都有起点和终点,但是,曲线的绘制方式基于控制点。quadratic曲线有一个控制点,而贝塞尔三次曲线使用两个控制点。曲线始终包含在路径中。

二次曲线

下面是 quadraticCurveTo 方法:

quadraticCurveTo(cp1x, cp1y, X, Y)

这四个参数是两对 X, Y 坐标,第一对(cp1x 和 cp1y)是曲线控制点的位置,第二对是曲线端点的位置。

正如所有其他形状一样,曲线是使用 moveTo(x, y) 方法开始绘制的,该方法提供曲线起点的 x 和 y 坐标。

下图是从两个端点到控制点的两条假想切线。 该曲线是由一条直线在切线周围移动时绘制的:

二次曲线的控制点。

示例

此示例使用一系列 quadraticCurveTo 方法来绘制具有波底的抽象图。请注意,控制点离端点越近,曲线在波底处变得越小。

二次曲线。

我们首先获取 canvas 元素并指定 2D 画布类型,然后通过调用 beginPath 方法创建路径。

context.beginPath();

将第一条曲线的起点的 x 和 y 坐标分别设置为 75 和 25。

context.moveTo(75, 25);

每条 quadratic 曲线的设置方式如下所示:

context.quadraticCurveTo(10, 80, 40, 130);
context.quadraticCurveTo(30, 90, 50, 130);
context.quadraticCurveTo(50, 100, 70, 130);
context.quadraticCurveTo(80, 110, 100, 130);
context.quadraticCurveTo(120, 120, 140, 130);

其中每个参数为:

  • cp1x
    控制点的 x 坐标。

  • cp1y
    控制点的 y 坐标。

  • x
    曲线端点的 x 坐标。

  • y
    曲线端点的 y 坐标。

注意,绘制曲线的顺序非常重要。 你可以删除一条或两条曲线,或更改曲线绘制的顺序以查看曲线的构造方式。

通过将 fillStyle 设置为等于表示绿色的 RGB 值来将颜色设置为绿色。

context.fillStyle = "rgb(100, 200, 50)";

最后,用 fill 函数对形状进行着色:

context.fill();

请注意,在此示例和下一个示例中,画布的大小已经增加至 150x150 像素:

<canvas id="canvas" width="150" height="150" />

下面是完整的示例:

// Get the canvas element.
var canvas = document.getElementById("canvas");

// Specify a 2-D canvas type.
var context = canvas.getContext("2d");
         
// Create the path.
context.beginPath();

// Set the starting point for the curve.
context.moveTo(75,25);

// Set each of the curves.        
context.quadraticCurveTo(10, 80, 40, 130);
context.quadraticCurveTo(30, 90, 50, 130);
context.quadraticCurveTo(50, 100, 70, 130);
context.quadraticCurveTo(80, 110, 100, 130);
context.quadraticCurveTo(120, 120, 140, 130);

// Set the color of the image to green.
context.fillStyle = "rgb(100, 200, 50)";

// Draw the image.
context.fill();

贝赛尔三次曲线

下面是 bezierCurveTo 方法:

bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

这六个参数是三对 X, Y 坐标:cp1x 和 cp1y 是曲线上第一个控制点的位置,cp2x 和 cp2y 是第二个控制点的位置,第三对是曲线终点的位置。

该曲线始于 moveTo(x, y) 方法中的 x 和 y 坐标。

从这两个控制点到端点绘制架线的切线。 该曲线是由一条直线在切线周围移动时绘制的,如下图中的黄色直线所示:

三次曲线的控制点。

示例

此示例使用一系列 bezierCurveTo 方法绘制具有波底的抽象图。

三次曲线示例。

在获取 canvas 元素并指定 2D 画布类型之后,我们将通过调用 beginPath 方法来创建路径。

context.beginPath();

将第一条曲线的起点的 x 和 y 坐标分别设置为 75 和 25。

context.moveTo(75, 25);

每条贝塞尔三次曲线的设置方式如下所示:

context.bezierCurveTo(10, 100, 10, 122, 20, 130);
context.bezierCurveTo(20, 100, 20, 122, 30, 130);
context.bezierCurveTo(40, 100, 40, 122, 50, 130);
context.bezierCurveTo(70, 100, 70, 122, 80, 130);
context.bezierCurveTo(110, 100, 110, 122, 120, 130);
context.bezierCurveTo(160, 100, 160, 122, 170, 130);

其中每个参数为:

  • cp1x
    第一个贝塞尔控制点的 x 坐标。

  • cp1y
    第一个贝塞尔控制点的 y 坐标。

  • cp2x
    第二个贝塞尔控制点的 x 坐标。

  • cp2y
    第二个贝塞尔控制点的 y 坐标。

  • x
    曲线端点的 x 坐标。

  • y
    曲线端点的 y 坐标。

注意,绘制曲线的顺序非常重要。 你可以删除一条或两条曲线,或更改曲线绘制的顺序以查看曲线的构造方式。

通过将 fillStyle 设置为等于表示红色的 RGB 值来将颜色设置为红色。

context.fillStyle = "rgb(200, 0, 0)";

最后,用 fill 函数对形状进行着色:

context.fill();

请注意,在此示例中,画布的大小已经增加至 150x150 像素:

<canvas id="canvas" width="150" height="150" />

下面是完整的代码示例:

// Get the canvas element.
var canvas = document.getElementById("canvas");

// Specify a 2-D canvas type.
var context = canvas.getContext("2d");

// Create the path.
context.beginPath();

// Set the starting point for the curve.
context.moveTo(75, 25);
 
// Set each of the curves.
context.bezierCurveTo(10, 100, 10, 122, 20, 130);
context.bezierCurveTo(20, 100, 20, 122, 30, 130);
context.bezierCurveTo(40, 100, 40, 122, 50, 130);
context.bezierCurveTo(70, 100, 70, 122, 80, 130);
context.bezierCurveTo(110, 100, 110, 122, 120, 130);
context.bezierCurveTo(160, 100, 160, 122, 170, 130);

// Set the color of the image to red.
context.fillStyle = "rgb(200, 0, 0)";

// Draw the image.
context.fill();

后续步骤

在本快速入门中,我们添加了一个用来创建透明绘制图面的 canvas 元素,使用 CSS 在该 canvas 元素周围创建了一个边框,而且使用 JavaScript 在该 canvas 元素上绘制了多个图形图像。

我们从该 canvas 元素获取了 2D 绘制上下文,因此,我们可以通过设置 fillRectfillStyle 来绘制矩形。我们以各种图形着色方式(如 RGB、十六进制值、预定义颜色和渐变)设置了 fillStyle

我们看到了如何使用 beginPath 方法开始绘制新路径,以及如何使用其他方法(如 moveTolineToarc)绘制直线、圆和曲线的组合。

在创建路径之后,我们使用 fillStylestrokeStyle 方法将路径呈现到了画布上。

接着,你将学习如何对画布图形进行动画处理,以及如何创建渐变。

如何对画布图形进行动画处理

如何创建渐变