舊文件

此處文件僅供參考,請自行考量時效性與適用程度,其他庫藏文件請參考文件頁面
我們亟需您的協助,進行共筆系統搬移、及文件整理工作,詳情請查閱參與我們

「用 Canvas 畫圖」修訂間的差異

出自 MozTW Wiki

較複雜的範例
(翻譯完成)
行 1: 行 1:
 
{{翻譯:mdc|Drawing_Graphics_with_Canvas|Drawing Graphics with Canvas}}
 
{{翻譯:mdc|Drawing_Graphics_with_Canvas|Drawing Graphics with Canvas}}
{{stub}}
 
  
 
== 簡介 ==
 
== 簡介 ==
行 155: 行 154:
 
這裡有定義兩個函數 <code>drawBowtie</code> 與 <code>dot</code>,且各被呼叫四次。每次呼叫前 <code>translate()</code> 與 <code>rotate()</code> 被用來設立 current transformation matrix(目前轉換矩陣)以定位中心點和蝴蝶結。<code>dot</code> 繪製一個中心在 <code>(0, 0)</code> 的黑方形。這個點用轉換矩陣來移位。<code>drawBowtie</code> 用收到的填滿樣式繪製一個蝴蝶結。
 
這裡有定義兩個函數 <code>drawBowtie</code> 與 <code>dot</code>,且各被呼叫四次。每次呼叫前 <code>translate()</code> 與 <code>rotate()</code> 被用來設立 current transformation matrix(目前轉換矩陣)以定位中心點和蝴蝶結。<code>dot</code> 繪製一個中心在 <code>(0, 0)</code> 的黑方形。這個點用轉換矩陣來移位。<code>drawBowtie</code> 用收到的填滿樣式繪製一個蝴蝶結。
  
因為矩陣運算有累積,每一段 <code>save()</code> 和 <code>restore()</code> 被用來返回到原來的 canvas 狀態。需注意的一點的是轉動永遠是繞著目前的原點,因此 <code>translate() rotate() translate()</code> 的呼叫的結果會與 code>translate() translate() rotate()</code> 一串的有所不同。
+
因為矩陣運算有累積,每一段 <code>save()</code> 和 <code>restore()</code> 被用來返回到原來的 canvas 狀態。需注意的一點的是轉動永遠是繞著目前的原點,因此 <code>translate() rotate() translate()</code> 的呼叫的結果會與 <code>translate() translate() rotate()</code> 一串的有所不同。
  
 
== 與 Apple <canvas> 的相容性 ==
 
== 與 Apple <canvas> 的相容性 ==
 +
 +
<code>&lt;canvas&gt;</code> 的實作大致上與 Apple 的相容。不過有些小地方需要注意一下。
  
 
=== 要求的 <code></canvas></code> 標籤 ===
 
=== 要求的 <code></canvas></code> 標籤 ===
 +
 +
<code>&lt;canvas&gt;</code> 在 Apple Safari 的實作裡與 <code>&lt;img&gt;</code> 相似,不需要結束標籤。但是要讓 <code><canvas></code> 在網上能有廣泛的用途,內容倒退(fallback content)的機制必須要有。因此 Mozilla 的實作有要求結束標籤。
 +
 +
如果倒退內容不需要,簡單的 <code>&lt;canvas id="foo" ...&gt;&lt;/canvas&gt;</code> 會與 Safari 和 Mozilla 完全相容 &mdash; Safari 會忽略那個結束標籤。
 +
 +
若是有倒退內容,則必須要運用到一些 CSS 技巧讓這內容不會在 Safari 裡出現,但在 Internet Explorer 裡要。
 +
<!--
 +
如果倒退內容有需要,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 內 ===
 
=== 把網頁內容畫到 Canvas 內 ===
 +
 +
Mozilla 的 <code>canvas</code> 有用 <code>drawWindow</code> 延伸。這個函數把一個 DOM 視窗內容的快照的畫入 canvas 內。舉例來說
 +
ctx.drawWindow(window, 0, 0, 100, 200, "rgb(0,0,0)");
 +
會把目前視窗的內容中,相對於檢視區左上角的 rectangle (0,0,100,200) 的部份,用黑色背景畫到 canvas 內。顏色設定如用 "rgba(0,0,0,0)" 會使內容有透明背景(但會較慢)。
 +
 +
有了這個方法,我們可以做一個隱藏式的 iframe,放入任何內容,然後畫到 canvas 中。這圖片會照目前的轉換(transformation)來縮放與轉動等。
  
 
== 參見 ==
 
== 參見 ==
行 171: 行 187:
 
* [http://weblogs.mozillazine.org/roc/archives/2005/05/rendering_web_p.html Rendering Web Page Thumbnails]
 
* [http://weblogs.mozillazine.org/roc/archives/2005/05/rendering_web_p.html Rendering Web Page Thumbnails]
 
* [http://awordlike.com/ The Lightweight Visual Thesaurus]
 
* [http://awordlike.com/ The Lightweight Visual Thesaurus]
 +
{{link2|技術傳教專案主頁|C|萬維網設計|HTML}}

於 2005年10月24日 (一) 00:12 的修訂

本文章為 Mozilla Developer Center 的 Drawing Graphics with Canvas 的翻譯。原文的作者與編修歷史可在它的歷史頁上看到。

簡介

Mozilla Firefox 1.5 裡有個新的,作用為可編程圖片的 HTML 元素。<canvas> 根據 WhatWG canvas 規格,而這又是根據 Apple Safari 裡的 <canvas> 實作。這元素可用來利用程式碼在客戶端上繪製圖表、介面、或其它自訂圖片。

<canvas> 會建立固定大小的繪圖空間,並會有一個或多個「繪製態」(rendering context)。在本文裡我們會專注在 2D 的繪製(這也是目前唯一有定義的 context)。在未來將會更多的 context 來提供其它類別的繪製,例如使用 OpenGL 的 3D 繪製。

2D Context(平面繪製態)

簡單的範例

我們一開始先來一個簡單的,一個半透明正方形蓋在另一個正方形之上的範例:

範例一
<html>
 <head>
  <script type="application/x-javascript">
function draw() {
 var canvas = document.getElementById("canvas");
 var ctx = canvas.getContext("2d");

 ctx.fillStyle = "rgb(200,0,0)";  // 把「填滿樣式」設為紅 200 綠 0 籃 0
 ctx.fillRect (10, 10, 50, 50);   // 畫一個填充的長方形

 ctx.fillStyle = "rgba(0, 0, 200, 0.5)"; // 把「填滿樣式」設為紅 0 綠 0 籃 200 透度 0.5
 ctx.fillRect (30, 30, 50, 50);          // 畫一個填充的長方形
}
  </script>
 </head>
 <body onload="draw()">
   <canvas id="canvas" width="300" height="300"></canvas>
 </body>
</html>

draw 函數先取得 canvas 元素,再取得 2d context。ctx 這物件可用來實際在畫板上繪製。本範例以用 CSS 顏色設定 fillStyle(填滿樣式)與呼叫 fillRect 的方式來繪出兩個方形。第二個 fillStyle 是用 rgba() 來一併定義顏色與透度(alpha)的值。

fillRectstrokeRect、與 clearRect calls 繪製填充、輪廓線、與透明的長方形。較複雜的形狀用路徑(path)。

使用路徑

beginPath 函數開始一個新的路徑,moveTolineToarcToarc、與類似的函數加入路徑片段。路徑可用 closePath 把頭尾連起來。建立路徑之後你可以用 fillstroke 來把路徑繪製到 canvas 上。

範例二
<html>
 <head>
  <script type="application/x-javascript">
function draw() {
  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");

  ctx.fillStyle = "red";

  ctx.beginPath();                        // 開始路徑
  ctx.moveTo(30, 30);                     // (起點)移到 30, 30
  ctx.lineTo(150, 150);                   // 做直線到 150, 150
  ctx.quadraticCurveTo(60, 70, 70, 150);  // 做一元二次方程曲線到 70, 150
  ctx.lineTo(30, 30);                     // 做直線到 30, 30
  ctx.fill();                             // 路徑內填色
}
   </script>
 </head>
 <body onload="draw()">
   <canvas id="canvas" width="300" height="300"></canvas>
 </body>
</html>

呼叫 fill()stroke() 會使得目前的路徑被用掉。要再塗滿或畫線的話,路徑必須要重建一次。

圖片狀態

Context 的如 fillStylestrokeStylelineWidth、與 lineJoin 的屬性屬於 目前的圖片狀態(graphics state)的一部份。Context 有 save()(儲存)與 restore()(返回)兩個函數讓目前的狀態可以存入狀態堆疊(stack)與從中移除。(注意路徑不屬於圖片狀態。)

較複雜的範例

現在來一個複雜點的範例。這範例用到路徑(paths)與狀態(state),並且它也介紹了目前轉換矩陣(current transformation matrix)的概念。Context 的 translate()(移動)、scale()(縮放),與 rotate()(轉動)方式會轉換目前的矩陣。所有繪製的點都會先用這個矩陣。

範例三
 <html>
  <head>
   <script type="application/x-javascript">

 // 畫蝴蝶結
 function drawBowtie(ctx, fillStyle) {
 
   ctx.fillStyle = "rgba(200,200,200,0.3)"; // 把「填滿樣式」設為灰色,0.3 透度
   ctx.fillRect(-30, -30, 60, 60);          // 畫一個填色的方形
 
   ctx.fillStyle = fillStyle;  // 設定填色

   ctx.globalAlpha = 1.0;    // 全域透度
   ctx.beginPath();          // 開始路徑
   ctx.moveTo(25, 25);       // (起點)移到 25, 25
   ctx.lineTo(-25, -25);     // 做直線到 -25, -25
   ctx.lineTo(25, -25);      // 做直線到 25, -25
   ctx.lineTo(-25, 25);      // 做直線到 -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 canvas = document.getElementById("canvas");
   var ctx = canvas.getContext("2d");

   // 注意其它的移動都是相對於這一個
   ctx.translate(45, 45);

   ctx.save();
   //ctx.translate(0, 0); // 不需要
   drawBowtie(ctx, "red");         // 畫綠色蝴蝶結
   dot(ctx);
   ctx.restore();
 
   ctx.save();                      // 儲存目前狀態
   ctx.translate(85, 0);            // 移動(向右 85)
   ctx.rotate(45 * Math.PI / 180);  // 轉動 45 度
   drawBowtie(ctx, "green");        // 畫綠色蝴蝶結
   dot(ctx);                        // 畫中心點
   ctx.restore();                   // 返回到先前的狀態 (轉動 0, 移動 45, 45)
 
   ctx.save();                      // 儲存目前狀態
   ctx.translate(0, 85);            // 移動(向下 85)
   ctx.rotate(135 * Math.PI / 180); // 轉動 135 度
   drawBowtie(ctx, "blue");         // 畫籃色蝴蝶結
   dot(ctx);                        // 畫中心點
   ctx.restore();                   // 返回到先前的狀態 (轉動 0, 移動 45, 45)
 
   ctx.save();
   ctx.translate(85, 85);
   ctx.rotate(90 * Math.PI / 180);
   drawBowtie(ctx, "yellow");       // 畫黃色蝴蝶結
   dot(ctx);
   ctx.restore();
 }
    </script>
  </head>
  <body onload="draw()">
    <canvas id="canvas" width="300" height="300"></canvas>
  </body>
 </html>

這裡有定義兩個函數 drawBowtiedot,且各被呼叫四次。每次呼叫前 translate()rotate() 被用來設立 current transformation matrix(目前轉換矩陣)以定位中心點和蝴蝶結。dot 繪製一個中心在 (0, 0) 的黑方形。這個點用轉換矩陣來移位。drawBowtie 用收到的填滿樣式繪製一個蝴蝶結。

因為矩陣運算有累積,每一段 save()restore() 被用來返回到原來的 canvas 狀態。需注意的一點的是轉動永遠是繞著目前的原點,因此 translate() rotate() translate() 的呼叫的結果會與 translate() translate() rotate() 一串的有所不同。

與 Apple <canvas> 的相容性

<canvas> 的實作大致上與 Apple 的相容。不過有些小地方需要注意一下。

要求的 </canvas> 標籤

<canvas> 在 Apple Safari 的實作裡與 <img> 相似,不需要結束標籤。但是要讓 <canvas> 在網上能有廣泛的用途,內容倒退(fallback content)的機制必須要有。因此 Mozilla 的實作有要求結束標籤。

如果倒退內容不需要,簡單的 <canvas id="foo" ...></canvas> 會與 Safari 和 Mozilla 完全相容 — Safari 會忽略那個結束標籤。

若是有倒退內容,則必須要運用到一些 CSS 技巧讓這內容不會在 Safari 裡出現,但在 Internet Explorer 裡要。

其它的功能

把網頁內容畫到 Canvas 內

Mozilla 的 canvas 有用 drawWindow 延伸。這個函數把一個 DOM 視窗內容的快照的畫入 canvas 內。舉例來說

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

會把目前視窗的內容中,相對於檢視區左上角的 rectangle (0,0,100,200) 的部份,用黑色背景畫到 canvas 內。顏色設定如用 "rgba(0,0,0,0)" 會使內容有透明背景(但會較慢)。

有了這個方法,我們可以做一個隱藏式的 iframe,放入任何內容,然後畫到 canvas 中。這圖片會照目前的轉換(transformation)來縮放與轉動等。

參見

[[Category:{{{5}}}|C用 Canvas 畫圖]] [[Category:{{{6}}}|C用 Canvas 畫圖]]

個人工具