跳转至内容

画布 2D 网页应用/HTML 网页应用

来自维基教科书,开放的书籍,为开放的世界

本章讨论使用单个画布元素进行渲染的 HTML 网页的基本结构。讨论包括最重要的渲染命令。假设读者熟悉 JavaScript(或 ECMAScript)。

一个例子

[编辑 | 编辑源代码]

以下 HTML 代码使用画布元素绘制一些文本和来自维基共享资源的图像。您应该使用您喜欢的文本编辑器创建一个新文件,将代码复制粘贴到其中,然后将文件保存到您的计算机上(最好使用“.html”文件扩展名)。然后使用您喜欢的网页浏览器打开该文件。(或者,它也可以在网上获得。)它应该在浅蓝色背景上显示 HTML5 图标上的“Hello, world!”文本。下面我们将详细讨论该示例。

<!DOCTYPE HTML>
<html>
  <head>
    <meta http-equiv="Content-type" content="text/html;charset=UTF-8">
    <script>
      var myImage = new Image();

      function init() {
        myImage.onload = update; // call update when image is loaded 
        myImage.src = "http://upload.wikimedia.org/wikipedia/" +
          "commons/thumb/2/25/HTML5_Shiny_Icon.svg/" +
          "200px-HTML5_Shiny_Icon.svg.png";
      }

      function update() {
        // get canvas and context
        var myCanvas = document.getElementById("mycanvas");
        var myContext = myCanvas.getContext("2d");
 
        // set canvas size to window size
        myCanvas.width = window.innerWidth; 
        myCanvas.height = window.innerHeight;
        
        // clear context to transparent black
        myContext.clearRect(0, 0, myCanvas.width, myCanvas.height);
 
        // render in front-to-back order 
        myContext.globalCompositeOperation = "destination-over"; 
 
        // write some text in black
        myContext.fillStyle = "#000000"; 
        myContext.font = "bold 48px Helvetica, sans-serif"; 
        myContext.textAlign = "center";
        myContext.textBaseline = "middle";
        myContext.fillText("Hello, world!", 170, 60);
 
        // draw the image (behind the text)
        myContext.drawImage(myImage, 10, 20, 50, 51);
 
        // fill the background of the canvas with light blue
        myContext.fillStyle = "#C0C0FF"; 
        myContext.fillRect(0, 0, myCanvas.width, myCanvas.height);
      }
    </script>
  </head>

  <body bgcolor="#000000" onload="init()" onresize="update()">
    <canvas width="400" height="300" id="mycanvas"
    style="position:absolute; left:0px; top:0px; "></canvas>
  </body>
</html>

如果您的网页浏览器无法正确显示网页,您应该尝试使用网页浏览器的开发者工具和错误消息列表来调试网页。不幸的是,如何打开这些工具取决于浏览器;因此,您必须查看您的网页浏览器的文档。

如果您更改了代码,请记住在您重新加载网页浏览器中的页面之前保存它。但是,某些浏览器可能会使用缓存版本而不是包含您更改的新版本。处理此问题的最安全方法是将新版本保存为一个新名称,并在网页浏览器中打开此新文件。

在本节中,将详细讨论示例中的所有代码。代码从一些 HTML 文本开始

<!DOCTYPE HTML>
<html>
  <head>
    <meta http-equiv="Content-type" content="text/html;charset=UTF-8">
    ...

这只是标准 HTML 代码来启动一个网页。meta 标签被包含进来,以避免有关未指定字符集的警告。

以下部分是包含 JavaScript 代码的script元素,我们现在跳过它。最后部分再次是 HTML 代码

     ...
  </head>

  <body bgcolor="#000000" onload="init()" onresize="update()">
    <canvas width="400" height="300" id="mycanvas"
      style="position:absolute; left:0px; top:0px; "></canvas>
  </body>
</html>

body标签指定了网页的内容。属性bgcolor="#000000"将背景颜色设置为黑色(如果它曾经可见)。属性onload="init()"指定了网页浏览器应该在网页加载后执行init函数(我们将在下面讨论)。onresize="update()"指定了只要浏览器窗口大小调整,就应该调用update函数(我们也将在下面讨论)。

在此网页中,网页主体中只有一个canvas元素。属性widthheight分别以 CSS 像素指定画布元素的宽度和高度(这可能与物理设备像素不同;例如,一个 CSS 像素通常对应于某些 iOS 设备视网膜显示屏上的 2×2 设备像素)。但是,画布元素的大小可以在 JavaScript 代码中更改,如以下所述。属性id="mycanvas"为画布元素指定一个 ID,以便它可以在 JavaScript 代码中识别。(如果有多个画布元素,这将特别有用。)最后,style="position:absolute; left:0px; top:0px; "将画布的左上角放置在网页的左上角,没有任何边距,这对于我们希望画布填充整个浏览器窗口非常重要。

在此示例中,canvas元素为空,即在<canvas></canvas>之间没有指定任何内容。如果在这些标签之间存在任何 HTML 元素,它们将被显示,如果网页浏览器不支持渲染到canvas元素中。

script元素定义了此网页的所有 JavaScript 代码。第一部分定义了一个全局变量myImage,它被初始化为一个新的空图像,以及函数init,它在网页浏览器加载网页主体后被调用(见上文)。

    ...
    <script>
      var myImage = new Image();

      function init() {
        myImage.onload = update; // call update when image is loaded 
        myImage.src = "http://upload.wikimedia.org/wikipedia/" +
          "commons/thumb/2/25/HTML5_Shiny_Icon.svg/" +
          "200px-HTML5_Shiny_Icon.svg.png";
      }
      ...

myImage.onload = update指定了函数update(见下文)应该在图像加载后被调用。下一行myImage.src = "http://...";指定了应该从哪里加载图像的 URL 地址。该字符串也可以指定相对于 HTML 文件位置的图像文件的路径名。

第二个函数称为update,因为它更新画布元素的内容。

      ...
      function update() {
        // get canvas and context
        var myCanvas = document.getElementById("mycanvas");
        var myContext = myCanvas.getContext("2d");
 
        // set canvas size to window size
        myCanvas.width = window.innerWidth; 
        myCanvas.height = window.innerHeight;
        
        // clear context to transparent black
        myContext.clearRect(0, 0, myCanvas.width, myCanvas.height);
 
        // render in front-to-back order 
        myContext.globalCompositeOperation = "destination-over"; 
 
        // write some text in black
        myContext.fillStyle = "#000000"; 
        myContext.font = "bold 48px Helvetica, sans-serif"; 
        myContext.textAlign = "center";
        myContext.textBaseline = "middle";
        myContext.fillText("Hello, world!", 170, 60);
 
        // draw the image (behind the text)
        myContext.drawImage(myImage, 10, 20, 50, 51);
 
        // fill the background of the canvas with light blue
        myContext.fillStyle = "#C0C0FF"; 
        myContext.fillRect(0, 0, myCanvas.width, myCanvas.height);
      }
    </script>
    ...

首先,使用document.getElementByID("mycanvas")检索画布元素(有关画布元素的 ID 的定义,请参见上文),并将其分配给变量myCanvas。对于此画布,使用myCanvas.getContext("2d")检索“画布 2D 上下文”,并将其分配给变量myContext。本维基教科书中讨论的所有渲染函数都使用 2D 上下文。

2D 上下文的大小由相应的画布指定。在此示例中,行myCanvas.width = window.innerWidth;myCanvas.height = window.innerHeight;将画布(以及 2D 上下文)的大小设置为浏览器窗口的大小。由于只要浏览器窗口大小调整就会调用update函数(见上文关于body元素的讨论),因此画布及其上下文始终设置为浏览器窗口的大小。

myContext.clearRect(0, 0, myCanvas.width, myCanvas.height);将整个上下文清除为透明黑色。(更改画布的大小通常也会清除上下文;因此,此行通常不是必需的。)

myContext.globalCompositeOperation = "destination-over";指定了适合从前到后渲染的合成操作;即,最前面的元素(遮挡所有其他元素的元素)首先渲染,然后遮挡除最前面元素之外所有元素的元素,依此类推。因此,背景必须最后渲染。这与我们在传统反向玻璃画中使用的方式相同。从前到后的渲染在计算机图形学中有点不寻常,但我们在本维基教科书中使用它,因为它与我们处理鼠标和触摸事件的方式一致。

myContext.fillStyle = "#000000";指定了以下命令应该使用黑色作为填充颜色。myContext.font = "bold 48px Helvetica, sans-serif";指定了以下命令应该使用 48 像素粗体 Helvetica 字体或默认无衬线字体(如果 Helvetica 不可使用)。行myContext.textAlign = "center";myContext.textBaseline = "middle";将垂直和水平对齐设置为居中;即,文本将以指定锚点为中心。行myContext.fillText("Hello, world!", 170, 60);然后使用已在先前行中指定的字体和填充颜色,以 x 坐标 170 和 y 坐标 60(坐标系的原点在画布的左上角)为中心编写字符串"Hello, world!"

下一行myContext.drawImage(myImage, 10, 20, 50, 51);绘制图像myImage,其左上角在 x 坐标 10 和 y 坐标 20 处,并将其重新缩放为 50 像素的宽度和 51 像素的高度。如果最后两个参数被跳过(即对于myContext.drawImage(myImage, 10, 20);),则将使用myImage的原始宽度和高度;因此,图像将不会被重新缩放。

类似于之前的一行,myContext.fillStyle = "#C0C0FF";指定填充颜色;在本例中,它是浅蓝色。(红色和绿色强度由 C0 指定,它是值 192 的十六进制代码,蓝色强度由 FF 指定,它是值 255 的十六进制代码,即最大强度。)行myContext.fillRect(0, 0, myCanvas.width, myCanvas.height);绘制一个填充矩形,其左上角在 x 坐标 0 和 y 坐标 0(即画布的左上角)处,宽度为myCanvas.width,高度为myCanvas.height。因此,矩形覆盖了整个画布。

这结束了对示例的讨论。为了熟悉代码和函数,强烈建议您进行练习;例如,通过更改颜色和字体,更改位置和大小,替换图像或添加其他图像、矩形或文本等。

关于渲染的更多内容

[编辑 | 编辑源代码]

画布元素的 2D 上下文中还有更多用于渲染的功能。它们都在万维网联盟 (W3C) 的文档“HTML Canvas 2D 上下文” 中进行了说明。但是,出于以下两个原因,我们不会在本维基教科书中讨论更多这些功能。

  1. 对于大多数交互式网页和 Web 应用程序的原型,所讨论的功能就足够了。
  2. 如果网页或 Web 应用程序的最终版本由专业的网页设计师设计,他或她通常更喜欢将图形元素创建为位图图像,这些图像可以使用上面讨论的 drawImage 函数进行渲染。

显然,在某些情况下,更多渲染功能是有用的,鼓励读者在这些情况下阅读 W3C 提供的 2D 上下文规范。


< Canvas 2D Web Apps

除非另有说明,否则本页面上的所有示例源代码均为公有领域。
华夏公益教科书