canvas 的基本用法

在本教程的開頭,我們將瞭解 <canvas> HTML 元素本身。在本頁的結尾,您將知道如何設定 canvas 2D 上下文,並已在瀏覽器中繪製了第一個示例。

<canvas> 元素

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

乍一看,<canvas> 看起來像 <img> 元素,唯一的明顯區別是它沒有 srcalt 屬性。事實上,<canvas> 元素只有兩個屬性:widthheight。這兩個屬性都是可選的,也可以使用 DOM 屬性設定。如果沒有指定 widthheight 屬性,canvas 的初始寬度將是300 畫素,高度將是150 畫素。該元素可以透過 CSS 任意調整大小,但在渲染時,影像會被縮放到以適應其佈局大小:如果 CSS 大小不遵循初始 canvas 的比例,它就會顯得失真。

注意:如果您的渲染看起來失真,請嘗試在 <canvas> 屬性中顯式指定 widthheight 屬性,而不是使用 CSS。

id 屬性不特定於 <canvas> 元素,而是 全域性 HTML 屬性之一,可以應用於任何 HTML 元素(例如,class)。提供 id 始終是個好主意,因為這使得在指令碼中識別它更加容易。

<canvas> 元素可以像任何普通影像一樣進行樣式設定(marginborderbackground…)。然而,這些規則不會影響 canvas 上的實際繪製。我們將在本教程的專門章節中瞭解如何進行繪製。當沒有將任何樣式規則應用於 canvas 時,它最初將是完全透明的。

可訪問內容

<canvas> 元素,與其他元素如 <img><video><audio><picture> 元素一樣,必須透過提供備用文字來使其可訪問,以便在媒體載入失敗或使用者無法按預期體驗時顯示。您應始終提供備用內容、字幕和替代文字,具體取決於媒體型別。

提供備用內容非常簡單:只需將替代內容插入到 <canvas> 元素內部,供螢幕閱讀器、爬蟲和其他自動化機器人訪問。預設情況下,瀏覽器會忽略容器內的內容,正常渲染 canvas,除非 <canvas> 不受支援。

例如,我們可以提供 canvas 內容的文字描述,或提供動態渲染內容的靜態影像。這看起來可能像這樣

html
<canvas id="stockGraph" width="150" height="150">
  current stock price: $3.15 + 0.15
</canvas>

<canvas id="clock" width="150" height="150">
  <img src="images/clock.png" width="150" height="150" alt="A clock" />
</canvas>

告訴使用者使用支援 canvas 的不同瀏覽器,對完全無法讀取 canvas 的使用者沒有幫助。提供有用的備用文字或子 DOM 會為本來不可訪問的元素增加可訪問性。

必需的 </canvas> 標籤

由於備用內容提供的機制,與 <img> 元素不同,<canvas> 元素需要閉合標籤(</canvas>)。如果缺少此標籤,則文件的其餘部分將被視為備用內容,並且不會顯示。

如果不需要備用內容,一個簡單的 <canvas id="foo" role="presentation" …></canvas> 與所有支援 canvas 的瀏覽器完全相容。這僅應用於 canvas 純粹用於展示的情況。

渲染上下文

<canvas> 元素建立了一個固定大小的繪圖表面,它公開了一個或多個渲染上下文,用於建立和操作顯示的內容。在本教程中,我們將重點介紹 2D 渲染上下文。其他上下文可能提供不同型別的渲染;例如,WebGL 使用基於 OpenGL ES 的 3D 上下文。

canvas 最初是空白的。要顯示內容,指令碼首先需要訪問渲染上下文並在其上繪製。<canvas> 元素有一個名為 getContext() 的方法,用於獲取渲染上下文及其繪圖功能。getContext() 接受一個引數,即上下文的型別。對於本教程涵蓋的 2D 圖形,您指定 "2d" 來獲取一個 CanvasRenderingContext2D

js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

指令碼中的第一行透過呼叫 document.getElementById() 方法來檢索 DOM 中表示 <canvas> 元素的節點。一旦您獲得了元素節點,就可以透過其 getContext() 方法訪問繪圖上下文。

檢查支援情況

在不支援 <canvas> 的瀏覽器中會顯示備用內容。指令碼也可以透過測試 getContext() 方法的存在來以程式設計方式檢查支援情況。我們上面的程式碼片段會變成這樣

js
const canvas = document.getElementById("canvas");

if (canvas.getContext) {
  const ctx = canvas.getContext("2d");
  // drawing code here
} else {
  // canvas-unsupported code here
}

一個骨架模板

這是一個極簡的模板,我們將以此為基礎進行後續示例。

注意:將指令碼嵌入 HTML 中不是一個好做法。我們在這裡這樣做是為了保持示例簡潔。

html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <title>Canvas tutorial</title>
    <style>
      canvas {
        border: 1px solid black;
      }
    </style>
  </head>
  <body>
    <canvas id="canvas" width="150" height="150"></canvas>
    <script>
      function draw() {
        const canvas = document.getElementById("canvas");
        const ctx = canvas.getContext("2d");
      }
      draw();
    </script>
  </body>
</html>

該指令碼包含一個名為 draw() 的函式,該函式在頁面載入完成後執行;這是透過將指令碼放在主要內容之後實現的。此函式或類似函式也可以使用 setTimeout()setInterval()load 事件處理程式呼叫,只要頁面已先載入。

此時,此文件應顯示為空白。

一個簡單的例子

首先,讓我們看一個繪製兩個相交矩形的示例,其中一個矩形具有 alpha 透明度。我們將在後面的示例中詳細探討其工作原理。將您的 script 元素內容更新為此

js
function draw() {
  const canvas = document.getElementById("canvas");
  const ctx = canvas.getContext("2d");

  ctx.fillStyle = "rgb(200 0 0)";
  ctx.fillRect(10, 10, 50, 50);

  ctx.fillStyle = "rgb(0 0 200 / 50%)";
  ctx.fillRect(30, 30, 50, 50);
}
draw();

這個示例看起來是這樣的