舊文件

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

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

出自 MozTW Wiki

使用路徑
較複雜的範例
行 6: 行 6:
 
Mozilla Firefox 1.5 裡有個新的,作用為可編程圖片的 HTML 元素。<code>&lt;canvas&gt;</code> 根據 [http://www.whatwg.org/specs/web-apps/current-work/#graphics WhatWG canvas 規格],而這又是根據 Apple Safari 裡的 <code>&lt;canvas&gt;</code> 實作。這元素可用來利用程式碼在客戶端上繪製圖表、介面、或其它自訂圖片。
 
Mozilla Firefox 1.5 裡有個新的,作用為可編程圖片的 HTML 元素。<code>&lt;canvas&gt;</code> 根據 [http://www.whatwg.org/specs/web-apps/current-work/#graphics WhatWG canvas 規格],而這又是根據 Apple Safari 裡的 <code>&lt;canvas&gt;</code> 實作。這元素可用來利用程式碼在客戶端上繪製圖表、介面、或其它自訂圖片。
  
<code>&lt;canvas&gt;</code> 會建立固定大小的繪圖空間,並會有一個或多個「繪製態」(rendering context)。在本文裡我們會專注在 2D 的繪製(這也是目前唯一有定義的繪製態)。在未來將會更多的繪製態來提供其它類別的繪製,例如使用 OpenGL 的 3D 繪製。
+
<code>&lt;canvas&gt;</code> 會建立固定大小的繪圖空間,並會有一個或多個「繪製態」(rendering context)。在本文裡我們會專注在 2D 的繪製(這也是目前唯一有定義的 context)。在未來將會更多的 context 來提供其它類別的繪製,例如使用 OpenGL 的 3D 繪製。
  
平面
+
== 2D Context(平面繪製態) ==
 
 
== 2D 繪製態 ==
 
  
 
=== 簡單的範例 ===
 
=== 簡單的範例 ===
行 38: 行 36:
 
  </html>
 
  </html>
  
<code>draw</code> 函數先取得 <code>canvas</code> 元素,再取得 <code>2d</code> 態。<code>ctx</code> 這物件可用來實際在畫板上繪製。本範例以用 CSS 顏色設定 fillStyle(填滿樣式)與呼叫 <code>fillRect</code> 的方式來繪出兩個方形。第二個 fillStyle 是用 <code>rgba()</code> 來一併定義顏色與透度(alpha)的值。
+
<code>draw</code> 函數先取得 <code>canvas</code> 元素,再取得 <code>2d</code> context。<code>ctx</code> 這物件可用來實際在畫板上繪製。本範例以用 CSS 顏色設定 fillStyle(填滿樣式)與呼叫 <code>fillRect</code> 的方式來繪出兩個方形。第二個 fillStyle 是用 <code>rgba()</code> 來一併定義顏色與透度(alpha)的值。
  
 
<code>fillRect</code>、<code>strokeRect</code>、與 <code>clearRect</code> calls 繪製填充、輪廓線、與透明的長方形。較複雜的形狀用路徑(path)。
 
<code>fillRect</code>、<code>strokeRect</code>、與 <code>clearRect</code> calls 繪製填充、輪廓線、與透明的長方形。較複雜的形狀用路徑(path)。
行 56: 行 54:
 
   
 
   
 
   ctx.beginPath();                        // 開始路徑
 
   ctx.beginPath();                        // 開始路徑
   ctx.moveTo(30, 30);                    // 移到 30, 30
+
   ctx.moveTo(30, 30);                    // (起點)移到 30, 30
   ctx.lineTo(150, 150);                  // 作直線到 150, 150
+
   ctx.lineTo(150, 150);                  // 做直線到 150, 150
   ctx.quadraticCurveTo(60, 70, 70, 150);  // 作一元二次方程曲線到 70, 150
+
   ctx.quadraticCurveTo(60, 70, 70, 150);  // 做一元二次方程曲線到 70, 150
   ctx.lineTo(30, 30);                    // 作直線到 30, 30
+
   ctx.lineTo(30, 30);                    // 做直線到 30, 30
   ctx.fill();                            // 塗滿路徑
+
   ctx.fill();                            // 路徑內填色
 
  }
 
  }
 
     </script>
 
     </script>
行 70: 行 68:
  
 
呼叫 <code>fill()</code> 或 <code>stroke()</code> 會使得目前的路徑被用掉。要再塗滿或畫線的話,路徑必須要重建一次。
 
呼叫 <code>fill()</code> 或 <code>stroke()</code> 會使得目前的路徑被用掉。要再塗滿或畫線的話,路徑必須要重建一次。
 +
 +
=== 圖片狀態 ===
 +
 +
Context 的如 <code>fillStyle</code>、<code>strokeStyle</code>、<code>lineWidth</code>、與 <code>lineJoin</code> 的屬性屬於
 +
目前的圖片狀態(graphics state)的一部份。Context 有 <code>save()</code>(儲存)與 <code>restore()</code>(返回)兩個函數讓目前的狀態可以存入狀態堆疊(stack)與從中移除。(注意路徑不屬於圖片狀態。)
 +
 +
=== 較複雜的範例 ===
 +
 +
現在來一個複雜點的範例。這範例用到路徑(paths)與狀態(state),並且它也介紹了目前轉換矩陣(current transformation matrix)的概念。Context 的
 +
<code>translate()</code>(移動)、<code>scale()</code>(縮放),與 <code>rotate()</code>(轉動)方式會轉換目前的矩陣。所有繪製的點都會先用這個矩陣。
 +
 +
[[Image:canvas_ex3.png|right|frame|範例三]]
 +
<pre>
 +
<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>
 +
</pre>
 +
 +
這裡有定義兩個函數 <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> 一串的有所不同。
 +
 +
== 與 Apple <canvas> 的相容性 ==
 +
 +
=== 要求的 <code></canvas></code> 標籤 ===
 +
 +
== 其它的功能 ==
 +
 +
=== 把網頁內容畫到 Canvas 內 ===
 +
 +
== 參見 ==
 +
* [http://developer.mozilla.org/en/docs/Canvas_tutorial Canvas tutorial]
 +
* [http://developer.mozilla.org/en/docs/A_Basic_RayCaster A Basic RayCaster]
 +
* [http://developer.apple.com/documentation/AppleApplications/Reference/SafariJSRef/Classes/Canvas.html Apple Canvas Documentation]
 +
* [http://weblogs.mozillazine.org/roc/archives/2005/05/rendering_web_p.html Rendering Web Page Thumbnails]
 +
* [http://awordlike.com/ The Lightweight Visual Thesaurus]

於 2005年10月23日 (日) 23:13 的修訂

本文章為 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() 的呼叫的結果會與 code>translate() translate() rotate() 一串的有所不同。

與 Apple <canvas> 的相容性

要求的 </canvas> 標籤

其它的功能

把網頁內容畫到 Canvas 內

參見

個人工具