JavaScript圖形實例:Canvas API


1.Canvas概述

      Canvas API(畫布)用於在網頁實時生成圖像,並且可以操作圖像內容,基本上它是一個可以用JavaScript操作的位圖(bitmap)。

      要使用HTML5在瀏覽器窗口中繪制圖形,首先需要在HTML文檔中新建一個canvas網頁元素。一般方法如下:

       <canvas id="myCanvas" width="400" height="300">

             您的瀏覽器不支持canvas!

      </canvas>

      上面這段代碼,表示建立了一個名為“myCanvas”的canvas網頁元素,它就是一塊畫布,該畫布的寬為400,高為300。有了這塊畫布,我們就可以使用JavaScript編寫程序,利用Canvas API在這塊畫布上繪制圖形。如果所用瀏覽器不支持Canvas API,則就會顯示canvas標簽中間的文字——“您的瀏覽器不支持canvas!”。

      每個canvas網頁元素都有一個對應的context對象(上下文對象),Canvas API定義在這個context對象上面。為了在canvas上繪制圖形,必須先得到一個畫布上下文對象的引用。為此,使用JavaScript編寫程序段如下:

      var canvas = document.getElementById('myCanvas');  // 取得網頁中的畫布對象

      var ctx = canvas.getContext('2d');       // 得到畫布上下文對象ctx

      上面代碼中,getContext方法指定參數2d,表示該canvas對象用於生成2D圖案(即平面圖案)。如果參數是3d,就表示用於生成3D圖像(即立體圖案)。

      當使用一個canvas元素的getContext(“2d”)方法時,返回的是CanvasRenderingContext2D對象,其內部表現為笛卡爾平面坐標。這就是Canvas畫布提供的一個用來作圖的平面空間,該空間的每個點都有自己的坐標,x表示橫坐標,y表示縱坐標。原點(0, 0)位於畫布左上角,x軸的正向是原點向右,y軸的正向是原點向下。

      每一個canvas元素僅有一個上下文對象。得到了這個上下文對象,就可以利用這個對象的屬性和方法進行圖形繪制了。

2.繪圖方法

2.1  繪制路徑

       在Canvas API中,上下文CanvasRenderingContext2D對象提供了一系列與圖形繪制相關的屬性和方法。其中,與路徑繪制相關的方法如下:

       void beginPath();                  //  開始繪制路徑

       void closePath();                   // 結束路徑繪制

       void moveTo(in float x, in float y);    // 設置線段的起點

       void lineTo(in float x, in float y);      // 設置線段的終點

       void bezierCurveTo(in float cp1x, in float cp1y, in float cp2x, in float cp2y, in float x, in float y);               // 繪制一條三次貝塞爾曲線

       void quadraticCurveTo(in float cpx, in float cpy, in float x, infloat y);                   // 繪制一條二次貝塞爾曲線

       void stroke();         // 給透明的線段着色,從而完成線段繪制

       void fill();            // 給閉合路徑填充顏色,填充色由fillStyle屬性指定

       與繪制路徑相關的屬性有:

       attribute float lineWidth;      // 線的寬度,默認為1

       attribute any strokeStyle;      // 着色的顏色,默認為black(黑色)

       attribute any fillStyle;         // 填充顏色,默認為black(黑色)

       attribute DOMString lineCap;  // 線段的箭頭樣式,僅有三個選項:butt(默認值)、round、square,其他值忽略

       下面通過幾個例子來說明繪制路徑的方法和屬性的使用。

      例1  繪制一條從(20,20)到(200,20)的一條紅色橫線。

<!DOCTYPE html>

<head>

<title>繪圖方法的使用</title>

<script type="text/javascript">

  function draw(id)

  {

     var canvas=document.getElementById(id);

     if (canvas==null)

        return false;

     var ctx=canvas.getContext('2d');

     ctx.beginPath();        // 開始路徑繪制

     ctx.moveTo(20, 20);    // 設置路徑起點,坐標為(20,20)

     ctx.lineTo(200, 20);    // 繪制一條到(200,20)的直線

     ctx.lineWidth = 1.0;    // 設置線寬

     ctx.strokeStyle = "#FF0000"; // 設置線條顏色為紅色

     ctx.stroke();          // 進行線的着色,這時整條線才變得可見

   }

</script>

</head>

<body onload="draw('myCanvas');">

<canvas id="myCanvas" width="400" height="300" style="border:3px double #996633;">

</canvas>

</body>

</html>

       將上述HTML代碼保存到一個html文本文件中,再在瀏覽器中打開包含這段HTML代碼的html文件,可以看到在畫布中繪制出一條長為180的紅色橫線。

       下面的例子中我們不再給出完整的HTML文件內容,只給出JavaScript編寫的與圖形繪制直接相關的代碼。例如例1源文件中加了注釋的6條語句。讀者需要自己試一試時,只需把下列各例給出的代碼去覆蓋例1中的6條注釋語句,其余部分保持不變即可。

       在繪制路徑時,moveto和lineto方法可以多次使用。最后,還可以使用closePath方法,自動繪制一條當前點到起點的線段,形成一個封閉圖形,省卻使用一次lineto方法。

       例2  在畫布中繪制一個紅色邊框的直角三角形和一個藍色邊框的等腰三角形。

     ctx.beginPath();

     ctx.moveTo(20,20);

     ctx.lineTo(20,100);   // 垂直直角邊

     ctx.lineTo(70,100);   // 水平直角邊

     ctx.lineTo(20,20);    // 斜邊

     ctx.strokeStyle="red";

     ctx.stroke();         // 進行着色,使得線段可見

     ctx.beginPath();

     ctx.moveTo(40,120);

     ctx.lineTo(20,180);   // 左邊的腰

     ctx.lineTo(60,180);   // 底邊

     ctx.closePath();      // 右邊的腰是通過自動封閉繪制得到

     ctx.strokeStyle="blue";

     ctx.stroke();  

       例3  線段箭頭的三種樣式的比較。

ctx.lineWidth=10;

ctx.strokeStyle="red";

ctx.beginPath();

ctx.lineCap='butt';

ctx.moveTo(100,50);

ctx.lineTo(250,50);

ctx.stroke();

ctx.beginPath();

ctx.lineCap='round';

ctx.moveTo(100,80);

ctx.lineTo(250,80);

ctx.stroke();

ctx.beginPath();

ctx.lineCap='square';

ctx.moveTo(100,110);

ctx.lineTo(250,110);

ctx.stroke(); 

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖1所示的三條線段。其中,第1根線段箭頭樣式為“butt”(為默認值),線段的頭和尾都是長方形,也就是不做任何的處理;第2根線段箭頭樣式為“round”,線段的頭和尾都增加一個半圓形的箭頭;第3根線段的樣式為“square”,線段的頭和尾都增加一個長方形,長度為線寬一半,高度為線寬。

圖1  繪制的3根紅色線段

      例4  繪制紅綠藍3個實心三角形。

     ctx.beginPath();

     ctx.moveTo(20,20);

     ctx.lineTo(20,100); 

     ctx.lineTo(70,100); 

     ctx.lineTo(20,20);  

     ctx.fillStyle="red";

     ctx.fill();         // 填充紅色三角形

     ctx.beginPath();

     ctx.moveTo(40,120);

     ctx.lineTo(20,180);

     ctx.lineTo(60,180);

     ctx.closePath();   

     ctx.fillStyle="green";

     ctx.fill();         // 填充綠色三角形

     ctx.beginPath();

     ctx.moveTo(70,20);

     ctx.lineTo(120,180);

     ctx.lineTo(140,150);

     ctx.fillStyle="blue";

     ctx.fill();         // 填充藍色三角形

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖2所示的三個實心三角形。

圖2 三個實心三角形

      通過上面的示例,我們可以知道,填充的形狀應該是封閉的路徑。如果路徑未關閉,那么 fill() 方法會從路徑結束點到開始點之間添加一條線,以關閉該路徑,然后填充該路徑。例如,圖2中藍色三角形構成的路徑並未關閉,調用fill()時,會自動添加直線關閉。

      貝賽爾曲線(Bezier curve)是計算機圖形學中相當重要的參數曲線。Canvas API中提供了兩個繪制貝塞爾曲線的方法。其中:

       quadraticCurveTo() 方法用於繪制一條二次貝塞爾曲線。

       二次貝塞爾曲線需要兩個點。第一個點(cpx,cpy)是用於二次貝塞爾計算中的控制點,第二個點(x,y)是曲線的結束點。曲線的開始點是當前路徑中最后一個點。如果路徑不存在,需要使用 beginPath() 和 moveTo() 方法來定義開始點。

      bezierCurveTo() 方法用於繪制一條三次貝塞爾曲線。

       三次貝塞爾曲線需要三個點。前兩個點(cp1x,cp1y)和(cp2x,cp2y)是用於三次貝塞爾計算中的控制點,第三個點(x,y)是曲線的結束點。曲線的開始點是當前路徑中最后一個點。如果路徑不存在,同樣需要使用 beginPath() 和 moveTo() 方法來定義開始點。

       例5  繪制一條二次貝塞爾曲線和一條三次貝塞爾曲線。

     ctx.beginPath();

     ctx.moveTo(20,20);

     ctx.quadraticCurveTo(20,100,200,20);

     ctx.stroke();

     ctx.beginPath();

     ctx.moveTo(20,120);

     ctx.bezierCurveTo(20,220,200,180,200,120);

     ctx.stroke();

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖3所示的兩條貝塞爾曲線。

圖3  兩條貝塞爾曲線

       例6  使用多個貝塞爾曲線來繪制一個對話氣泡。

    ctx.beginPath();

    ctx.moveTo(75,25);

    ctx.quadraticCurveTo(25,25,25,62.5);

    ctx.quadraticCurveTo(25,100,50,100);

    ctx.quadraticCurveTo(50,120,30,125);

    ctx.quadraticCurveTo(60,120,65,100);

    ctx.quadraticCurveTo(125,100,125,62.5);

    ctx.quadraticCurveTo(125,25,75,25);

    ctx.stroke();

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖4所示的對話氣泡。

圖4 對話氣泡

      例7  使用多個貝塞爾曲線來繪制一個紅心。 

     ctx.fillStyle="red";

     ctx.beginPath();

     ctx.moveTo(75,40);

     ctx.bezierCurveTo(75,37,70,25,50,25);

     ctx.bezierCurveTo(20,25,20,62.5,20,62.5);

     ctx.bezierCurveTo(20,80,40,102,75,120);

     ctx.bezierCurveTo(110,102,130,80,130,62.5);

     ctx.bezierCurveTo(130,62.5,130,25,100,25);

     ctx.bezierCurveTo(85,25,75,37,75,40);

     ctx.fill();

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖5所示的紅心圖案。

 

圖5  紅心

      例8  通過循環繪制一個9行9列的棋盤。

     ctx.strokeStyle="red";

     ctx.lineWidth=3;

     ctx.beginPath();

     for (i=50;i<=450;i+=50)

     {

         ctx.moveTo(i,50);

         ctx.lineTo(i,450);

         ctx.moveTo(50,i);

         ctx.lineTo(450,i);

     }

     ctx.stroke();

      為顯示完整的棋盤,請將畫布的寬和高均設置為500。在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖6所示的棋盤。

 

圖6  棋盤

2.2  繪制矩形

       在Canvas API中,上下文CanvasRenderingContext2D對象提供的與矩形繪制相關的方法如下:

void rect(in float x, in float y, in float w, in float h);      // 建立一個矩形路徑

void clearRect(in float x, in float y, in float w, in float h);  // 清除給定矩形區域的內容

void fillRect(in float x, in float y, in float w, in float h);   // 填充給定的矩形區域

void strokeRect(in float x, in float y, in float w, in float h);  // 繪制給定的矩形邊框

這個幾個方法中給定的四個參數分別為矩形左上角頂點的x坐標、y坐標,以及矩形的寬w和高h。

例9  繪制紅綠藍三個矩形邊框。

     ctx.beginPath();

     ctx.lineWidth="8";

     ctx.strokeStyle="red";

     ctx.rect(15,15,150,150);

     ctx.stroke();                // 繪制紅色矩形

     ctx.beginPath();

     ctx.lineWidth="3";

     ctx.strokeStyle="#00FF00";

     ctx.strokeRect(30,30,40,50);  // 繪制綠色矩形

     ctx.beginPath();

     ctx.lineWidth="8";

     ctx.strokeStyle="blue";

     ctx.moveTo(80,50);

     ctx.lineTo(80,120);

     ctx.lineTo(140,120);

     ctx.lineTo(140,50);

     ctx.closePath();

     ctx.stroke();   //     //  繪制藍色矩形

      在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖7所示的三個矩形。

圖7  三個矩形邊框

      例10  繪制一個邊長為100的正方形,邊框采用藍色,內部用紅色填充。

     ctx.fillStyle="red";

     ctx.strokeStyle="blue";

     ctx.lineWidth=2;

     ctx.fillRect(50,50,100,100);

     ctx.strokeRect(50,50,100,100);

      在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖8所示的正方形。

 

圖8  正方形

      在沒有進行坐標旋轉的情況下,采用rect()和strokeRect()方法繪制的矩形一定是兩條邊與x軸平行,兩條邊與y軸平行。若要繪制與坐標軸不平行的矩形,可以采用繪制4條線的方法完成。

      例11  繪制矩形中的矩形。要求矩形里的矩形其頂點在外面矩形的中點上。

     var x = [50,50,250,250];

     var y = [50,250,250,50];

     ctx.strokeStyle="red";

     ctx.lineWidth=3;

     for (i=1;i<=4;i++)

     {

         ctx.beginPath();

         ctx.moveTo(x[0],y[0]);

         for (k=1;k<=3;k++)

           ctx.lineTo(x[k],y[k]);

         ctx.closePath();

         ctx.stroke();

         var tx=x[0];

         var ty=y[0];

         for (k=0;k<3;k++)

         {

             x[k]=(x[k]+x[k+1])/2;

             y[k]=(y[k]+y[k+1])/2;

         }

         x[3]=(tx+x[3])/2;

         y[3]=(ty+y[3])/2;

     }

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖9所示的正方形。

圖9  正方形中的正方形

       例12  繪制國際象棋棋盤。

     for (i=0;i<8;i++)

     {

         for (j=0;j<8;j++)

         {

              if ((i+j)%2==0)   

                 ctx.fillStyle = 'black';

              else

                 ctx.fillStyle= 'white';

              ctx.fillRect(j*50,i*50,50,50);

         }

     }

       為顯示完整的棋盤,請將畫布的寬和高均設置為400。在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖10所示的國際象棋棋盤。

 

圖10  國際象棋棋盤 

      例13  根據給定數據繪制柱狀圖。

     var data = [100, 50, 20, 30, 100];

     var colors = [ "red","orange", "yellow","green", "blue"];

     ctx.fillStyle = "white";

     ctx.fillRect(0,0,canvas.width,canvas.height);

     for(var i=0; i<data.length; i++)

     {

         var dp = data[i];

         ctx.fillStyle = colors[i];

         ctx.fillRect(25+i*50, 280-dp*2, 50, dp*2);

     }

      在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖11所示的柱狀圖。 

圖11  柱狀圖

2.3  繪制圓形和扇形

      在Canvas API中,上下文CanvasRenderingContext2D對象提供的與圓形和弧等繪制相關的方法如下:

       void arc(in float x, in float y, in float radius, in float startAngle, in float endAngle, in boolean anticlockwise);

       void arcTo(in float x1, in float y1, in float x2, in float y2, in float radius);

      其中,arc方法用來繪制扇形。參數x和y是圓心坐標,radius是半徑,startAngle和endAngle則是扇形的起始角度和終止角度(以弧度表示),anticlockwise表示作圖時應該逆時針畫(true)還是順時針畫(false)。

      arcTo() 方法用於在畫布上創建介於兩個切線之間的弧/曲線。繪制出子路徑最后一個點(x0,y0)和(x1,y1)以及(x1,y1)和(x2,y2)構成的兩條直線間半徑為radius的最短弧線,並用直線連接(x0,y0)

例14  繪制圓弧。

     ctx.strokeStyle="red";

     ctx.fillStyle="orange";

     for(var i=0;i<3;i++)

     {

        for(var j=0;j<4;j++)

        {

            ctx.beginPath();

            x = 50+j*100;     

            y = 50+i*100;    

            radius = 45;                   

            startAngle = 0;   

            endAngle = Math.PI/2+(Math.PI*j)/2;

            anticlockwise = i%2==0 ? false : true; 

            ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);

            if (i>1)

               ctx.fill();

            else

               ctx.stroke();

        }

     }

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖12所示的圓弧。

 

圖12  圓弧及填充

      通過這個例子還可以加深理解:當調用fill()函數時,所有沒有閉合的形狀都會自動閉合,因此可以不調用closePath()函數。但是調用stroke()時不會自動閉合。

      例15  繪制9個大小不一的圓。

     ctx.fillStyle="red";

     ctx.lineWidth=1;

     for (var i=1;i<10;i++)

     {

        ctx.beginPath();

        ctx.arc(i*20,i*20,i*10,0,Math.PI*2,true);

        ctx.closePath();

        ctx.fillStyle='rgba(255,0,0,0.25)';

        ctx.fill();

     }

      在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖13所示的圖形。

圖13  逐漸放大的圓

      例16  根據給定數據繪制餅圖。

     var data = [100, 50, 20, 30, 100];

     ctx.fillStyle = "white";

     ctx.fillRect(0,0,canvas.width,canvas.height);

     var colors = [ "red","orange", "yellow","green", "blue"];

     var total = 0;

     for(var i=0; i<data.length; i++)

         total += data[i];

     var prevAngle = 0;

     for(var i=0; i<data.length; i++) 

     {

         var fraction = data[i]/total;

         var angle = prevAngle + fraction*Math.PI*2;

         ctx.fillStyle = colors[i];

         ctx.beginPath();

         ctx.moveTo(150,150);

         ctx.arc(150,150, 100, prevAngle, angle, false);

         ctx.lineTo(150,150);

         ctx.fill();

         ctx.strokeStyle = "black";

         ctx.stroke();

         prevAngle = angle;

     }

      在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖14所示的餅圖。

 

圖14  餅圖

2.4  繪制文本

      在Canvas API中,上下文CanvasRenderingContext2D對象提供的與文本繪制相關的方法如下:

       void fillText(in DOMString text, in float x, in float y, optionalin float maxWidth);

       void strokeText(in DOMString text, in float x, in float y, optionalin float maxWidth);

      這兩個方法用來繪制文本,它的前三個參數分別為文本內容、起點的x坐標、y坐標。其中:fillText方法為繪制填充的文字;strokeText方法為對文字進行描邊,不填充內部區域,通常用來添加空心字。

      與文本相關的屬性有:

      attribute DOMString font;         // 設置字體,默認為10px sans-serif

      attribute DOMString textAlign;    //  設置對齊方式,有"start", "end", "left", "right", "center"等,默認為"start"

      attribute DOMString textBaseline;  //設置文字對齊基線,有"top", "hanging", "middle", "alphabetic", "ideographic", "bottom" 等取值,默認為”alphabetic"

例17  在畫布上添加兩行文字。

  ctx.font = "Bold 50px 隸書";

  ctx.fillStyle = "Black";

  ctx.fillText("我們是中國人", 10, 50);

  ctx.strokeText("我們熱愛我們的祖國", 10, 150);

      在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖15所示的文本。

 

圖15  文本繪制

      注意:fillText方法不支持文本斷行,即所有文本出現在一行內。所以,如果要生成多行文本,只有調用多次fillText方法。

例18  繪制包含數據說明的柱狀圖。

     var data = [100, 50, 20, 30, 100];

     var colors = [ "red","orange", "yellow","green", "blue"];

     ctx.fillStyle = "white";

     ctx.fillRect(0,0,canvas.width,canvas.height);

     for(var i=0; i<data.length; i++)

     {

         var dp = data[i];

         ctx.fillStyle = colors[i];

         ctx.fillRect(25+i*50, 280-dp*2, 50, dp*2);

     }

     ctx.fillStyle = "black";

     ctx.lineWidth = 2;

     ctx.beginPath();

     ctx.moveTo(25,10);

     ctx.lineTo(25,280);

     ctx.lineTo(290,280);

     ctx.stroke();

     ctx.fillStyle = "black";

     for(var i=0; i<6; i++)

     {

         ctx.fillText((5-i)*20 + "",4, i*40+80);

         ctx.beginPath();

         ctx.moveTo(25,i*40+80);

         ctx.lineTo(30,i*40+80);

         ctx.stroke();

     }

     var labels = ["JAN","FEB","MAR","APR","MAY"];

     for(var i=0; i<5; i++)

         ctx.fillText(labels[i], 40+ i*50, 290);   

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖16所示的包含數據說明的柱狀圖。

 

圖16  包含數據說明的柱狀圖

      還可以為文本等設置陰影。

例19  為文本設置陰影。

  ctx.shadowOffsetX = 3;    // 設置水平位移

  ctx.shadowOffsetY = 3;    // 設置垂直位移

  ctx.shadowBlur = 2;      // 設置模糊度

  ctx.shadowColor = "rgba(0, 0, 0, 0.5)";    // 設置陰影顏色

  ctx.font = "50px 宋體";

  ctx.fillStyle = "Black";

  ctx.fillText("我們是中國人", 10, 50);

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖17所示的文字陰影效果。

圖17  文字陰影

2.5  圖形剪切

      在Canvas API中,上下文CanvasRenderingContext2D對象提供了一個用於圖形剪切的方法。

       void clip();

       剪切(clip)路徑和普通的 canvas 圖形差不多,不同的是它的作用是遮罩,用來隱藏沒有遮罩的部分,如圖18所示。紅邊五角星就是裁切路徑,所有在路徑以外的部分都不會在 canvas 上繪制出來。默認情況下,canvas 有一個與它自身一樣大的剪切路徑(也就是沒有剪切效果)。

 

圖18  剪切示意圖

例20  一個簡單的剪切示例。

   ctx.fillStyle = 'red';

   ctx.fillRect(0,0,400,300);

   ctx.beginPath();

   ctx.moveTo(200,50);

   ctx.lineTo(100,250);

   ctx.lineTo(300,250);

   ctx.closePath();

   ctx.lineWidth = 10;

   ctx.stroke();

   ctx.clip();

   ctx.fillStyle = 'yellow';

   ctx.fillRect(0,0,400,150);

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖19所示的三角形剪切。

 

圖19  三角形剪切

      在這個例子中,先畫了一個與 canvas 一樣大小(寬400,高300)的紅色方形作為背景,然后用 clip方法創建一個三角形的剪切路徑。剪切路徑創建之后,所有出現在它里面的東西才會畫出來。這樣在其后繪制高度為畫布一半的矩形填充時,只有三角形剪切路徑里面的內容才會繪制出來。

      設定了剪切區域之后,無論在Canvas上繪制什么,只有落在剪切區域內的那部分才能得以顯示,其余都會被遮蔽掉。

      例21  cilp方法的進一步理解。

// 繪制第一個圓

ctx.beginPath();   

ctx.fillStyle = 'red';

ctx.arc(200, 100, 100, 0, Math.PI * 2, false);

ctx.fill();

// 繪制第二個圓

ctx.beginPath();

ctx.fillStyle = 'blue';

ctx.arc(100, 150, 100, 0, Math.PI * 2, false);

ctx.fill();

// 繪制第三個圓

ctx.beginPath();

ctx.fillStyle = 'green';

ctx.arc(300, 150, 100, 0, Math.PI * 2, false);

ctx.fill();

// 繪制第四個圓

ctx.beginPath();

ctx.fillStyle = 'brown';

ctx.arc(200, 200,100, 0, Math.PI * 2, false);

ctx.fill();

ctx.lineWidth = 10;

ctx.strokeStyle='black';

ctx.stroke();

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖20所示的4個圓。

圖20  沒有使用clip方法的4個圓

      若在第3個圓繪制后插入一條語句“ctx.clip();”,則在畫布中繪制出如圖21所示的圖形。從圖21可以看出第4個圓(棕色的),只有落在第3個圓中的部分被繪制出來。

 

圖21 在第3個圓之后使用clip()方法

      若clip()方法往上移,放到第2個圓的后面,則在畫布中繪制出如圖22所示的圖形。從圖22可以看出第3個圓(藍色的)完全沒有被繪制出來,因為第3個圓與第2個圓相切,沒有交集;第4個圓(棕色的)只有落在第2個圓中的部分被繪制出來。

 

圖22 在第2個圓之后使用clip()方法

      若再把clip()方法往上移,放到第1個圓的后面,則在畫布中繪制出如圖23所示的圖形。從圖23可以看出,第1個圓為剪切區域,第2、3、4個圓只有落在第1個圓中的部分才被繪制出來。

圖23 在第1個圓之后使用clip()方法

      當使用剪切函數clip()進行繪圖后,可能需要取消該剪切區域或者重新定義剪切區域。在Canvas中,可以通過save()函數和restore()函數來實現。在構建剪切區域之前保存狀態,完成剪切區域內的繪圖之后進行狀態讀取。

       例如,在例21的程序中,在第2個圓繪制后插入語句“ctx.save();”和“ctx.clip();”,在第3個圓繪制后插入語句“ctx.restore();”,則在畫布中繪制出如圖24所示的圖形。從圖24可以看出,第3個圓(藍色的)完全沒有被繪制出來,因為第3個圓與第2個圓相切,沒有交集;第4個圓(棕色的)全部被繪制出來,此時取消了剪切區域。

圖24  在第3個圓繪制后取消剪切區域

例22  采用clip實現簡單的探照燈效果。

<!DOCTYPE html>

<head>

<title>簡單探照燈</title>

</head>

<body>

<canvas id="myCanvas" width="400" height="400" style="border:3px double #996633;">

</canvas>

<script type="text/javascript">

    var rot=10;

    var canvas=document.getElementById('myCanvas');

    var ctx=canvas.getContext('2d');

    setInterval("draw()",100);

    function draw()

    {

           ctx.clearRect(0,0,400,400);

           ctx.save();

           ctx.fillStyle="black";

           ctx.fillRect(0,0,400,400);

        ctx.beginPath();

        ctx.arc(rot,200,40,0,Math.PI*2,true);

        ctx.closePath();

        ctx.fillStyle="white";

        ctx.fill();

           ctx.clip();

           ctx.font="bold 45px 隸書";

        ctx.textAlign="center";

           ctx.textBaseline="middle";

           ctx.fillStyle="#FF0000";

           ctx.fillText("中國北京歡迎您!",200,200);

           ctx.restore();

        rot=rot+10;

        if (rot>400) rot=10;

    }

</script>

</body>

</html>

       在瀏覽器中打開包含這段HTML代碼的html文件,可以看到在畫布中呈現出如圖25所示的簡單探照燈效果。

 

圖25  簡單的探照燈

3.圖形變換

在圖形學中,可以對圖形進行平移、縮放和旋轉等變換操作。

在Canvas API中,上下文CanvasRenderingContext2D對象提供的與圖形變換相關的方法如下:

void translate(in float x, in float y);  // 平移Canvas的原點到指定的坐標點(x,y)

void rotate(in float angle);         //  按給定的弧度angle順時針旋轉

void scale(in float x, in float y);    //  按給定的縮放倍率進行縮放

void setTransform(in float m11, in float m12, in float m21, infloat m22, in float dx, in float dy);                  // 將當前轉換重置為單位矩陣

void transform(in float m11, in float m12, in float m21, in floatm22, in float dx, in float dy);                      // 按矩陣進行變換

       在進行圖形變換前先保存上下文環境(狀態)是一個良好的習慣。大多數情況下,調用 restore()方法比手動恢復原先的狀態要簡單得多。例如,在一個循環中做平移操作但沒有保存和恢復canvas 的狀態,很可能到最后會發現有些東西不見了,那是因為它很可能已經超出 canvas 范圍以外了。

3.1  save和restore方法

       save方法用於保存上下文環境,restore方法用於恢復到上一次保存的上下文環境。

       在Canvas中,每個上下文對象都包含一個繪圖狀態的堆,繪圖狀態包含下列內容:

(1)當前的變換矩陣;

(2)當前的剪切區域(clip);

       (3)當前的屬性值:fillStyle、font、globalAlpha、globalCompositeOperation、lineCap、 lineJoin、lineWidth、miterLimit、shadowBlur、shadowColor、shadowOffsetX、shadowOffsetY、 strokeStyle、textAlign、textBaseline等。

例23  save方法和restore方法的簡單應用示例。

     ctx.fillStyle = "red";

     ctx.fillRect(10,10,80,80);

     ctx.save();

     ctx.shadowOffsetX = 10;

     ctx.shadowOffsetY = 10;

     ctx.shadowBlur = 5;

     ctx.shadowColor = "rgba(0,0,0,0.5)";

     ctx.fillStyle = "blue";

     ctx.fillRect(100,10,80,80);

     ctx.restore();

     ctx.fillRect(200,10,80,80);

     ctx.fillStyle = "orange";

     ctx.fillRect(300,10,80,80);

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖26所示的4個矩形。

 

圖26  4個矩形

      這4個矩形中,第1個矩形填充紅色,之后保存狀態(填充色為紅色),第2個矩形是一個有黑色陰影的填充色為藍色的矩形;接着,使用restore方法,恢復了保存前的設置,繪制了一個沒有陰影的填充色為紅色的第3個矩形,第4個矩形是一個填充色為橙色的矩形,也沒有陰影。

      若去掉代碼中的“ctx.restore();”語句,不恢復狀態,則繪制的4個矩形如圖27所示。體會圖27與圖26的區別。

圖27  不執行“ctx.restore();”繪制的4個矩形

3.2  translate、scale和rotate方法

       translate() 方法實現坐標平移,例如,進行ctx.translate(dx,dy);后,坐標原點移到(dx,dy)處,這樣程序繪圖時給出的坐標值(x,y),相對於canvas默認的坐標原點(0,0),應該為(x+dx,y+dy)。

例24  translate簡單應用示例。

      ctx.fillStyle = "red";

      ctx.fillRect(10,10,80,80);

      ctx.fillStyle = "blue";

      ctx.translate(80,80);

      ctx.fillRect(10,10,80,80);

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖26所示的2個矩形。從圖中看出,在坐標位置 (10,10) 處繪制一個紅色填充矩形后,將坐標原點平移到(80,80),這樣再次繪制填充藍色的矩形從位置 (90,90) 處開始繪制。

 

圖28  平移后的藍色矩形

  例25  連續坐標平移的示例。

    ctx.fillStyle = 'rgba(255,0,0,0.5)';

    for (i = 0; i<5; i++)

     {

         ctx.translate(50,50);

         ctx.fillRect(0,0,100,100);

      }

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖29所示的5個矩形。

圖29  坐標平移后的5個矩形

       scale() 方法實現圖形的縮放。需要注意的是使用scale方法對繪圖進行縮放后,所有之后的繪圖也會被縮放,包括坐標定位也會被縮放。例如,執行ctx.scale(2,2)后,繪圖將定位於距離畫布左上角兩倍遠的位置。

例26  scale簡單應用示例。

    ctx.fillStyle = "red";

    ctx.fillRect(10,10,80,80);

    ctx.save();

    ctx.fillStyle = "blue";

    ctx.scale(2,2);

    ctx.fillRect(50,10,80,80);

    ctx.restore();

    ctx.fillStyle = "green";

    ctx.scale(0.5,0.5);

    ctx.fillRect(10,200,80,80);

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖30所示的3個矩形。從圖中看出,在坐標位置 (10,10) 處繪制一個紅色填充矩形后,ctx.scale(2,2);將繪圖放大兩倍,這樣繪制填充藍色的矩形從位置 (100,20) 處開始繪制,其寬和高均是紅色填充矩形的2倍;恢復上下文環境后,ctx.scale(0.5,0.5);將繪圖縮小1倍,這樣繪制填充綠色的矩形從位置 (5,100) 處開始繪制,其寬和高均是紅色填充矩形的一半。

 

圖30  矩形的縮放

        若去掉代碼中的“ctx.restore();”語句,不恢復狀態,則繪制的3個矩形如圖31所示。體會圖31與圖30的區別。綠色矩形的大小之所以與紅色矩形一樣,是因為一個東西放大2倍后再縮小1倍,正好恢復原樣。

       通過這個示例一定得明白,圖形變換的設置一定是在前一個狀態的基礎上進行的。因此在進行圖形變換時,根據需要通過save()方法保存狀態,restore()方法恢復狀態是非常重要的。

圖31  不執行“ctx.restore();”繪制的3個矩形

例27  連續圖形放大的示例。

    ctx.fillStyle = 'rgba(255,0,0,0.5)';

    for (i = 0; i<4; i++)

    {

         ctx.scale(2,2);

         ctx.fillRect(5,5,10,10);

     }

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖32所示的4個矩形。

 

圖32  依次放大后的4個矩形

      rotate()方法實現圖形的旋轉,其中參數給出的旋轉角度angle以弧度計。如需將角度degress轉換為弧度,可以使用 degrees*Math.PI/180 公式進行計算。

例28  將矩形旋轉45°。

     ctx.fillStyle = "red";

     ctx.fillRect(150,50,80,80);

     ctx.fillStyle = "blue";

     ctx.rotate(45*Math.PI/180);

     ctx.fillRect(150,50,80,80);

      在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖33所示的2個矩形,其中藍色矩形順時針旋轉了45°。

  

圖33  順時針旋轉了45°的藍色矩形

例29  連續旋轉的矩形。

     ctx.translate(200,200);

     ctx.fillStyle = 'rgba(255,0,0,0.5)';

     for (i = 0; i<6; i++)

     {

         ctx.rotate(Math.PI/3);

         ctx.fillRect(0,0,100,50);

      }

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖34所示的6個矩形。

圖34  旋轉的矩形

3.3  transform 和setTransform方法

transform() 方法是通過變換矩陣實現變換。例如,語句ctx.transform(a,b,c,d,e,f);中包含6個參數,其中:

a      水平縮放繪圖

b     水平傾斜繪圖

c      垂直傾斜繪圖

d     垂直縮放繪圖

e      水平移動繪圖

f      垂直移動繪圖

通過transform() 方法可以縮放、旋轉、移動並傾斜當前的繪圖環境。

例如,ctx.translate(dx,dy)可以用

context.transform(0,1,1,0,dx,dy);

或    context.transform(1,0,0,1,dx,dy);    來替代。

又例如, ctx.transform(0.95,0,0,0.95,30,30);

可以替代  ctx.translate(30,30);

ctx.scale(0.95.0.95);     同時縮放和平移。

例30  transform() 方法簡單應用示例。

        ctx.fillStyle="red";

        ctx.fillRect(0,0,150,50)

ctx.transform(1,0.5,0,1,30,10);

ctx.fillStyle="blue";

ctx.fillRect(0,0,150,50);

ctx.transform(1,0.5,-0.5,1,30,10);

ctx.fillStyle="green";

ctx.fillRect(0,0,150,50);

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖35所示的3個矩形。由圖可以看出,藍色矩形水平方向傾斜了,綠色矩形在水平方向和垂直方向上都傾斜了。

圖35  應用transform() 方法后繪制的矩形

      setTransform()方法也是通過變換矩陣實現變換,它與transform()的使用方法類同,區別在於:每次調用 setTransform() 時,都會重置前一個變換矩陣然后構建新的矩陣;二每次調用 transform() 時,它都會在前一個變換矩陣基礎上構建變換矩陣。

       例如,將例30中的第2個transform 方法“ctx.transform(1,0.5,-0.5,1,30,10);”改寫為“ctx.setTransform(1,0.5,-0.5,1,30,10);”,則在瀏覽器窗口中繪制出如圖36所示的圖形。由圖可知,藍色矩形基本被綠色矩形覆蓋,只露出一個小角。這是因為繪制藍色矩形之前,使用的是setTransform() 方法,會重置變換矩陣,而不是在繪制藍色矩形的變換矩陣基礎上進行,因此藍色矩形與綠色矩形水平傾斜一致,水平與垂直方向平移也一致,只是綠色矩形多進行了垂直傾斜,因此將藍色矩形露出一小角。

圖36  應用setTransform() 方法后繪制的矩形

例31  通過變換繪制螺旋。

   ctx.translate(200,50);

   for(var i=0; i<50; i++)

   {

        ctx.save();

        ctx.transform(0.95,0,0,0.95,30,30);

        ctx.rotate(Math.PI/12);

        ctx.beginPath();

        ctx.fillStyle =  'rgba(255,0,0,0.5)';

        ctx.arc(0,0,50,0,Math.PI*2,true);

        ctx.closePath();

        ctx.fill();

   }

       在瀏覽器中打開包含這段JavaScript代碼的html文件,可以看到在畫布中繪制出如圖37所示的螺旋圖形。

 

圖37  螺旋圖

4.圖像處理

       canvas更有意思的一項特性就是圖像操作能力。可以用於動態的圖像合成或者作為圖形的背景,以及游戲界面等等。瀏覽器支持的任意格式的外部圖片都可以使用,比如PNG、GIF或者JPEG。

4.1  圖像繪制

drawImage()   方法可以向畫布上繪制圖像、畫布或視頻。

要在畫布上繪制圖片,可以使用drawImage方法。該方法有三種不同的調用形式:

(1)ctx.drawImage(img,x,y);              // 在畫布上定位圖像

(2)ctx.drawImage(img,x,y,width,height);  

// 在畫布上定位圖像,並規定圖像的寬度和高度

(3)ctx.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);

 // 剪切圖像,並在畫布上定位被剪切的部分。

其中,各參數的說明如下:

img      規定要使用的圖像、畫布或視頻。

sx        可選。開始剪切的 x 坐標位置。

sy        可選。開始剪切的 y 坐標位置。

swidth     可選。被剪切圖像的寬度。

sheight    可選。被剪切圖像的高度。

x         在畫布上放置圖像的 x 坐標位置。

y         在畫布上放置圖像的 y 坐標位置。

width      可選。要使用的圖像的寬度。(伸展或縮小圖像)

height     可選。要使用的圖像的高度。(伸展或縮小圖像)

       在使用drawImage()方法將圖像繪制到畫布上之前,要獲得需要繪制的圖像。canvas的API可以使用圖像源的類型有:

(1)HTMLImageElement。

這些圖片或者由Image()函數構造出來的,或者頁面中的某一個<img>元素。

(2)HTMLVideoElement。

用一個HTML的 <video>元素作為圖片源,可以從視頻中抓取當前幀作為一個圖像。

(3)HTMLCanvasElement。

      可以使用另一個 <canvas> 元素作為圖片源。這種類型的一個常用的應用就是將第二個canvas作為另一個大的 canvas 的縮略圖。

      獲取到需要在canvas上繪制的圖片的方式有以下幾種:

      (1)使用相同頁面內的圖片或其它 canvas 元素。

      通過document.images 集合、document.getElementsByTagName 方法或者 document.getElementById 方法來獲取頁面內的圖片(如果已知圖片元素的 ID)。

      使用其它 canvas 元素和引用頁面內的圖片類似地,用 document.getElementsByTagName 或 document.getElementById 方法來獲取其它 canvas 元素。

例32  在畫布中繪制頁面上的圖片。

<!DOCTYPE html>

<head>

<title>在畫布中繪制頁面上的圖片</title>

<script type="text/javascript">

  function draw(id)

  {

      var canvas=document.getElementById(id);

      if (canvas==null)

        return false;

       var ctx=canvas.getContext('2d');

      var img=document.getElementById("myImg");

      ctx.drawImage(img,10,10);

   }

</script>

</head>

<body onload="draw('myCanvas');">

<img src="aaa.jpg" id="myImg">

<canvas id="myCanvas" width="400" height="400" style="border:3px double #996633;">

</canvas>

</body>

</html>

       在瀏覽器中打開保存這段HTML代碼的html文件,可以看到在畫布中出現如圖38所示的頁面。頁面中,左邊的圖片是頁面中的img元素,右邊是在畫布中繪制的左邊的圖片。

圖38  圖片繪制(一)

      若將上面程序中的“ctx.drawImage(img,10,10);”改寫為“ctx.drawImage(img,50,50,200,200,20,20,250,150);”,則在瀏覽器中顯示如圖39所示的內容。右邊canvas中繪制的圖片是左邊原圖的部分剪切,並進行了水平拉伸。

 

圖39  圖片繪制(二)

      (2)創建圖像。

       用腳本創建一個新的 HTMLImageElement 對象。要實現這個方法,可以使用Image()構造函數。

var img = new Image();      //  創建一個img元素

img.src = 'myImage.png';    //  設置圖片源地址

當腳本執行后,圖片開始裝載。

由於圖像的載入需要時間,drawImage方法只能在圖像完全載入后才能調用,因此上面的代碼需要改寫。可用load時間來保證不會在加載完畢之前使用這個圖片。

var img = new Image();     // 創建img元素

img.onload = function(){

  //  執行drawImage語句

}

img.src = 'myImage.png';   // 設置圖片源地址

例33  編寫如下的HTML文件內容。

<!DOCTYPE html>

<head>

<title>創建圖像對象使用圖片進行繪制</title>

<script type="text/javascript">

  function draw(id)

  {

     var canvas=document.getElementById(id);

     if (canvas==null)

        return false;

     var ctx=canvas.getContext('2d');

     var image = new Image();

     image.src = 'aaa.jpg'; 

     image.onload=function(){

            ctx.drawImage(image,10,10);

     }

   }

</script>

</head>

<body onload="draw('myCanvas');">

<canvas id="myCanvas" width="400" height="400" style="border:3px double #996633;">

</canvas>

</body>

</html>

      在瀏覽器中打開保存這段HTML代碼的html文件,可以看到在畫布中出現如圖40所示的頁面。

 

圖40  創建圖像對象使用圖片進行繪制

      (3)通過 data: url 方式嵌入圖像。

       Data urls 允許用一串 Base64 編碼的字符串的方式來定義一個圖片。其優點就是圖片內容即時可用,無須再到服務器兜一圈。缺點就是圖像沒法緩存,圖片大的話內嵌的 url 數據會相當的長。

4.2  像素級操作

      在Canvas API中,上下文CanvasRenderingContext2D對象提供了三個方法用於像素級操作:createImageData, getImageData, 和putImageData。

       (1)createImageData()方法。

       createImageData() 方法創建新的空白ImageData 對象。新對象的默認像素值 transparent black。

       ImageData對象保存了圖像像素值。每個對象有三個屬性:width,height和data。data 屬性類型為CanvasPixelArray,用於儲存width*height*4個像素值。每一個像素有RGB值和透明度alpha值(其值為 0 至255,包括alpha在內)。像素的順序從左至右,從上到下,按行存儲。其中:

R - 紅色 (0-255)

G - 綠色 (0-255)

B - 藍色 (0-255)

A - alpha 通道 (0-255;0 是透明的,255 是完全可見的)

transparent black 表示 (0,0,0,0)。

      像素值以數組形式存在,由於每個像素有4條信息,因此數組的大小是 ImageData 對象的4倍。可以使用 ImageDataObject.data.length獲得數組的大小。

      createImageData() 方法有兩種調用形式:

      1) var imgData=ctx.createImageData(width,height);

      以指定的尺寸(以像素計)創建新的 ImageData 對象,其中參數width給定ImageData 對象的寬度,height給定ImageData 對象的高度。

      2)var  imgData=ctx.createImageData(imageData);

      創建與指定的另一個 ImageData 對象尺寸相同的新 ImageData 對象(不會復制圖像數據)。

      (2)putImageData()方法。

      putImageData() 方法用於將圖像數據(從指定的 ImageData 對象)放回畫布上。其調用格式為:

ctx.putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight);

各參數的說明如下:

imgData      規定要放回畫布的 ImageData 對象。

x             ImageData 對象左上角的 x 坐標,以像素計。

y             ImageData 對象左上角的 y 坐標,以像素計。

dirtyX         可選。水平值(x),以像素計,在畫布上放置圖像的位置。

dirtyY         可選。垂直值(y),以像素計,在畫布上放置圖像的位置。

dirtyWidth      可選。在畫布上繪制圖像所使用的寬度。

dirtyHeight     可選。在畫布上繪制圖像所使用的高度。

例34  createImageData和putImageData方法的簡單應用。

var imgData=ctx.createImageData(100,100);

for (var i=0;i<imgData.data.length;i+=4)

  {

  imgData.data[i+0]=255;

  imgData.data[i+1]=0;

  imgData.data[i+2]=0;

  imgData.data[i+3]=255;

  }

ctx.putImageData(imgData,10,10);

       上述代碼執行后,會在畫布中繪制一個紅色矩形,矩形的左上角坐標為(10,10),寬度和高度均為100。

       (3)getImageData()方法。

       getImageData方法可以用來讀取(復制)Canvas的內容,返回一個ImageData對象,包含了每個像素的信息。其調用形式為:

var imgData=ctx.getImageData(x,y,width,height);

各參數描述如下:

x         開始復制的左上角位置的 x 坐標。

y         開始復制的左上角位置的 y 坐標。

width      將要復制的矩形區域的寬度。

height     將要復制的矩形區域的高度。

      imgData對象有一個data屬性,它的值是一個一維數組。該數組的值依次是每個像素的紅、綠、藍、alpha通道值,每個值的范圍是0~255。可以通過操作這個數組的值達到操作圖像的目的。修改這個數組以后,使用putImageData方法將數組內容重新繪制在Canvas上。

       例35  通過操作像素數組的值來操作圖像。

<!DOCTYPE html>

<head>

<title>通過操作像素數組的值來操作圖像</title>

<script type="text/javascript">

  function draw(id1,id2)

  {

    var canvas1=document.getElementById(id1);

    var ctx1=canvas1.getContext('2d');

    var canvas2=document.getElementById(id2);

    var ctx2=canvas2.getContext('2d');

    var imgData1=ctx1.createImageData(100,100);

    for (i=0;i<imgData1.data.length;i+=4)

   {

  imgData1.data[i+0]=255;

  imgData1.data[i+1]=0;

  imgData1.data[i+2]=0;

  imgData1.data[i+3]=255;

 }

        ctx1.putImageData(imgData1,10,10);

       var imgData2=ctx1.getImageData(10,10,100,100);

       for (i=imgData2.data.length/4;i<imgData2.data.length*3/4;i+=4)

      {

            imgData2.data[i+0]=0;

             imgData2.data[i+2]=255;

      }

      ctx2.putImageData(imgData2,10,10);

 }

</script>

</head>

<body onload="draw('myCanvas1','myCanvas2');">

<canvas id="myCanvas1" width="200" height="200" style="border:3px double #996633;">

</canvas>

<canvas id="myCanvas2" width="200" height="200" style="border:3px double #996633;">

</canvas>

</body>

</html>

       在瀏覽器中打開保存這段HTML代碼的html文件,可以看到在瀏覽器窗口中顯示如圖41所示的內容。

圖41  通過操作像素數組的值來操作圖像的示例

       關於更多的Canvas API的知識,可以參閱文檔“HTML 5 Canvas 參考手冊”(https://www.w3school.com.cn/tags/html_ref_canvas.asp)。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM