Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Drawing graphics with canvas

Most of this content (but not the documentation on drawWindow) has been rolled into the more expansive Canvas tutorial, this page should probably be redirected there as it's now redundant but some information may still be relevant.

介紹

  在 Firefox 1.5, Firefox 引入了新的 HTML 元素 <canvas> 來繪製圖形。<canvas> 是基於 WHATWG canvas specification 的技術 (其發軔於蘋果公司在 Safari 上的實做)。 我們可以用它來在使用者端進行圖形和 UI 元件的渲染。

  <canvas> 創建了一個具有一致多個 rendering contexts 的區域。在本文中,我們著重於 2D rendering context 的部份。對於 3D 圖形,您可以參考 WebGL rendering context

2D Rendering Context

先來個簡單的範例

  以下的程式碼做了一個簡單的展示:繪製兩個部份交疊的矩形 (其中一個矩形有透明屬性) :

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');

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

  ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
  ctx.fillRect (30, 30, 55, 50);
}

ScreenshotLive sample

  這個名為 draw 的函式從 canvas element 取得 2d context。物件 ctx 可以被用來在 canvas 上頭繪製圖形。從程式碼可以看出,我們簡單的藉由設定 fillStyle 繪製了兩個顏色不同的矩形,並透過 fillRect 設定其位置。此外,第二個矩形透過 rgba() 配置了透明屬性。

  關於更複雜的圖形繪製,我們可以使用 fillRect, strokeRect 和 clearRect,他們分別可以畫出填滿的矩形, 僅有外框的矩形以及矩形區域清除。

路徑的使用

  beginPath 函式用來初始一段路徑的繪製,並且可以透過 moveTo, lineTo, arcTo, arc 以及相關的函式來描述路徑內容。要結束的時候呼叫 closePath 即可。一旦路徑描述完畢,就可以透過 fill 或 stroke 來渲染該路徑在 canvas 上。

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');

  ctx.fillStyle = "red";

  ctx.beginPath();
  ctx.moveTo(30, 30);
  ctx.lineTo(150, 150);
  // was: ctx.quadraticCurveTo(60, 70, 70, 150); which is wrong.
  ctx.bezierCurveTo(60, 70, 60, 70, 70, 150); // <- this is right formula for the image on the right ->
  ctx.lineTo(30, 30);
  ctx.fill();
}

ScreenshotLive sample

  呼叫 fill() 或 stroke() 代表該路徑已經被使用。若要重新進行填滿等動作,則需要重頭創造一次路徑。

圖像狀態

  fillStyle, strokeStyle, lineWidth 和 lineJoin 等屬性是 graphics state 的一部分。關於這些屬性的修改,您可以透過 save() 及 restore() 來進行操作。

一個更為複雜的範例

  接著我們來看一個稍微複雜一點的範例,它同時引入了路徑, 狀態的修改以及變換矩陣。

function drawBowtie(ctx, fillStyle) {
 
  ctx.fillStyle = "rgba(200,200,200,0.3)";
  ctx.fillRect(-30, -30, 60, 60);
 
  ctx.fillStyle = fillStyle;
  ctx.globalAlpha = 1.0;
  ctx.beginPath();
  ctx.moveTo(25, 25);
  ctx.lineTo(-25, -25);
  ctx.lineTo(25, -25);
  ctx.lineTo(-25, 25);
  ctx.closePath();
  ctx.fill();
}
 
function dot(ctx) {
  ctx.save();
  ctx.fillStyle = "black";
  ctx.fillRect(-2, -2, 4, 4);
  ctx.restore();
}
 
function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');

  // note that all other translates are relative to this one
  ctx.translate(45, 45);

  ctx.save();
  //ctx.translate(0, 0); // unnecessary
  drawBowtie(ctx, "red");
  dot(ctx);
  ctx.restore();
 
  ctx.save();
  ctx.translate(85, 0);
  ctx.rotate(45 * Math.PI / 180);
  drawBowtie(ctx, "green");
  dot(ctx);
  ctx.restore();
 
  ctx.save();
  ctx.translate(0, 85);
  ctx.rotate(135 * Math.PI / 180);
  drawBowtie(ctx, "blue");
  dot(ctx);
  ctx.restore();
 
  ctx.save();
  ctx.translate(85, 85);
  ctx.rotate(90 * Math.PI / 180);
  drawBowtie(ctx, "yellow");
  dot(ctx);
  ctx.restore();
}

ScreenshotLive sample

  我們自定義了兩個函式: drawBowtie 以及 dot,並且個別呼叫了四次。在呼叫他們之前,我們使用了 translate()rotate() 來設定接著要繪製圖形的 transformation matrix,這將改變最終 dot 和 bowtie 的位置。dot 繪製了一個以 (0, 0) 為中心的小黑正方形,而 drawBowtie 產生了一個填滿的蝴蝶結樣貌的圖形。

  save() 和 restore() 規範了一系列動作的初始和結尾。一個值得注意的地方是,旋轉的動作是基於該圖形當下所在的位置, 所以 translate() -> rotate() -> translate() 的結果會和 translate() -> translate() -> rotate() 不同。

和 Apple <canvas> 的相容性

For the most part, <canvas> is compatible with Apple's and other implementations. There are, however, a few issues to be aware of, described here.

</canvas> tag 是必要的

In the Apple Safari implementation, <canvas> is an element implemented in much the same way <img> is; it does not have an end tag. However, for <canvas> to have widespread use on the web, some facility for fallback content must be provided. Therefore, Mozilla's implementation has a required end tag.

If fallback content is not needed, a simple <canvas id="foo" ...></canvas> will be fully compatible with both Safari and Mozilla -- Safari will simply ignore the end tag.

If fallback content is desired, some CSS tricks must be employed to mask the fallback content from Safari (which should render just the canvas), and also to mask the CSS tricks themselves from IE (which should render the fallback content).

canvas {
  font-size: 0.00001px !ie;
}

其他特性

藉由 Canvas 渲染網頁內容

This feature is only available for code running with Chrome privileges. It is not allowed in normal HTML pages. Read why.

Mozilla's canvas is extended with the drawWindow() method. This method draws a snapshot of the contents of a DOM window into the canvas. For example,

ctx.drawWindow(window, 0, 0, 100, 200, "rgb(255,255,255)");

would draw the contents of the current window, in the rectangle (0,0,100,200) in pixels relative to the top-left of the viewport, on a white background, into the canvas. By specifying "rgba(255,255,255,0)" as the color, the contents would be drawn with a transparent background (which would be slower).

It is usually a bad idea to use any background other than pure white "rgb(255,255,255)" or transparent, as this is what all browsers do, and many websites expect that transparent parts of their interface will be drawn on white background.

With this method, it is possible to fill a hidden IFRAME with arbitrary content (e.g., CSS-styled HTML text, or SVG) and draw it into a canvas. It will be scaled, rotated and so on according to the current transformation.

Ted Mielczarek's tab preview extension uses this technique in chrome to provide thumbnails of web pages, and the source is available for reference.

Note: Using canvas.drawWindow() while handling a document's onload event doesn't work. In Firefox 3.5 or later, you can do this in a handler for the MozAfterPaint event to successfully draw HTML content into a canvas on page load.

更多資訊

文件標籤與貢獻者

 此頁面的貢獻者: fscholz, sailplaneTW
 最近更新: fscholz,