欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
JavaScript圖形實(shí)例:Canvas API

1.Canvas概述

      Canvas API(畫(huà)布)用于在網(wǎng)頁(yè)實(shí)時(shí)生成圖像,并且可以操作圖像內容,基本上它是一個(gè)可以用JavaScript操作的位圖(bitmap)。

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

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

             您的瀏覽器不支持canvas!

      </canvas>

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

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

      var canvas = document.getElementById('myCanvas');  // 取得網(wǎng)頁(yè)中的畫(huà)布對象

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

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

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

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

2.繪圖方法

2.1  繪制路徑

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

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

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

       void moveTo(in float x, in float y);    // 設置線(xiàn)段的起點(diǎn)

       void lineTo(in float x, in float y);      // 設置線(xiàn)段的終點(diǎn)

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

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

       void stroke();         // 給透明的線(xiàn)段著(zhù)色,從而完成線(xiàn)段繪制

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

       與繪制路徑相關(guān)的屬性有:

       attribute float lineWidth;      // 線(xiàn)的寬度,默認為1

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

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

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

       下面通過(guò)幾個(gè)例子來(lái)說(shuō)明繪制路徑的方法和屬性的使用。

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

<!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();        // 開(kāi)始路徑繪制

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

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

     ctx.lineWidth = 1.0;    // 設置線(xiàn)寬

     ctx.strokeStyle = "#FF0000"; // 設置線(xiàn)條顏色為紅色

     ctx.stroke();          // 進(jìn)行線(xiàn)的著(zhù)色,這時(shí)整條線(xiàn)才變得可見(jiàn)

   }

</script>

</head>

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

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

</canvas>

</body>

</html>

       將上述HTML代碼保存到一個(gè)html文本文件中,再在瀏覽器中打開(kāi)包含這段HTML代碼的html文件,可以看到在畫(huà)布中繪制出一條長(cháng)為180的紅色橫線(xiàn)。

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

       在繪制路徑時(shí),moveto和lineto方法可以多次使用。最后,還可以使用closePath方法,自動(dòng)繪制一條當前點(diǎn)到起點(diǎn)的線(xiàn)段,形成一個(gè)封閉圖形,省卻使用一次lineto方法。

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

     ctx.beginPath();

     ctx.moveTo(20,20);

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

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

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

     ctx.strokeStyle="red";

     ctx.stroke();         // 進(jìn)行著(zhù)色,使得線(xiàn)段可見(jiàn)

     ctx.beginPath();

     ctx.moveTo(40,120);

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

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

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

     ctx.strokeStyle="blue";

     ctx.stroke();  

       例3  線(xiàn)段箭頭的三種樣式的比較。

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(); 

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

圖1  繪制的3根紅色線(xiàn)段

      例4  繪制紅綠藍3個(gè)實(shí)心三角形。

     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();         // 填充藍色三角形

       在瀏覽器中打開(kāi)包含這段JavaScript代碼的html文件,可以看到在畫(huà)布中繪制出如圖2所示的三個(gè)實(shí)心三角形。

圖2 三個(gè)實(shí)心三角形

      通過(guò)上面的示例,我們可以知道,填充的形狀應該是封閉的路徑。如果路徑未關(guān)閉,那么 fill() 方法會(huì )從路徑結束點(diǎn)到開(kāi)始點(diǎn)之間添加一條線(xiàn),以關(guān)閉該路徑,然后填充該路徑。例如,圖2中藍色三角形構成的路徑并未關(guān)閉,調用fill()時(shí),會(huì )自動(dòng)添加直線(xiàn)關(guān)閉。

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

       quadraticCurveTo() 方法用于繪制一條二次貝塞爾曲線(xiàn)。

       二次貝塞爾曲線(xiàn)需要兩個(gè)點(diǎn)。第一個(gè)點(diǎn)(cpx,cpy)是用于二次貝塞爾計算中的控制點(diǎn),第二個(gè)點(diǎn)(x,y)是曲線(xiàn)的結束點(diǎn)。曲線(xiàn)的開(kāi)始點(diǎn)是當前路徑中最后一個(gè)點(diǎn)。如果路徑不存在,需要使用 beginPath() 和 moveTo() 方法來(lái)定義開(kāi)始點(diǎn)。

      bezierCurveTo() 方法用于繪制一條三次貝塞爾曲線(xiàn)。

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

       例5  繪制一條二次貝塞爾曲線(xiàn)和一條三次貝塞爾曲線(xiàn)。

     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();

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

圖3  兩條貝塞爾曲線(xiàn)

       例6  使用多個(gè)貝塞爾曲線(xiàn)來(lái)繪制一個(gè)對話(huà)氣泡。

    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();

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

圖4 對話(huà)氣泡

      例7  使用多個(gè)貝塞爾曲線(xiàn)來(lái)繪制一個(gè)紅心。 

     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();

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

 

圖5  紅心

      例8  通過(guò)循環(huán)繪制一個(gè)9行9列的棋盤(pán)。

     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();

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

 

圖6  棋盤(pán)

2.2  繪制矩形

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

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

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);  // 繪制給定的矩形邊框

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

例9  繪制紅綠藍三個(gè)矩形邊框。

     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();   //     //  繪制藍色矩形

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

圖7  三個(gè)矩形邊框

      例10  繪制一個(gè)邊長(cháng)為100的正方形,邊框采用藍色,內部用紅色填充。

     ctx.fillStyle="red";

     ctx.strokeStyle="blue";

     ctx.lineWidth=2;

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

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

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

 

圖8  正方形

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

      例11  繪制矩形中的矩形。要求矩形里的矩形其頂點(diǎn)在外面矩形的中點(diǎn)上。

     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;

     }

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

圖9  正方形中的正方形

       例12  繪制國際象棋棋盤(pán)。

     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);

         }

     }

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

 

圖10  國際象棋棋盤(pán) 

      例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);

     }

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

圖11  柱狀圖

2.3  繪制圓形和扇形

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

       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方法用來(lái)繪制扇形。參數x和y是圓心坐標,radius是半徑,startAngle和endAngle則是扇形的起始角度和終止角度(以弧度表示),anticlockwise表示作圖時(shí)應該逆時(shí)針畫(huà)(true)還是順時(shí)針畫(huà)(false)。

      arcTo() 方法用于在畫(huà)布上創(chuàng )建介于兩個(gè)切線(xiàn)之間的弧/曲線(xiàn)。繪制出子路徑最后一個(gè)點(diǎn)(x0,y0)和(x1,y1)以及(x1,y1)和(x2,y2)構成的兩條直線(xiàn)間半徑為radius的最短弧線(xiàn),并用直線(xiàn)連接(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();

        }

     }

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

 

圖12  圓弧及填充

      通過(guò)這個(gè)例子還可以加深理解:當調用fill()函數時(shí),所有沒(méi)有閉合的形狀都會(huì )自動(dòng)閉合,因此可以不調用closePath()函數。但是調用stroke()時(shí)不會(huì )自動(dòng)閉合。

      例15  繪制9個(gè)大小不一的圓。

     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();

     }

      在瀏覽器中打開(kāi)包含這段JavaScript代碼的html文件,可以看到在畫(huà)布中繪制出如圖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;

     }

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

 

圖14  餅圖

2.4  繪制文本

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

       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);

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

      與文本相關(guān)的屬性有:

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

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

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

例17  在畫(huà)布上添加兩行文字。

  ctx.font = "Bold 50px 隸書(shū)";

  ctx.fillStyle = "Black";

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

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

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

 

圖15  文本繪制

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

例18  繪制包含數據說(shuō)明的柱狀圖。

     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);   

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

 

圖16  包含數據說(shuō)明的柱狀圖

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

例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);

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

圖17  文字陰影

2.5  圖形剪切

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

       void clip();

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

 

圖18  剪切示意圖

例20  一個(gè)簡(jiǎn)單的剪切示例。

   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);

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

 

圖19  三角形剪切

      在這個(gè)例子中,先畫(huà)了一個(gè)與 canvas 一樣大?。▽?00,高300)的紅色方形作為背景,然后用 clip方法創(chuàng )建一個(gè)三角形的剪切路徑。剪切路徑創(chuàng )建之后,所有出現在它里面的東西才會(huì )畫(huà)出來(lái)。這樣在其后繪制高度為畫(huà)布一半的矩形填充時(shí),只有三角形剪切路徑里面的內容才會(huì )繪制出來(lái)。

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

      例21  cilp方法的進(jìn)一步理解。

// 繪制第一個(gè)圓

ctx.beginPath();   

ctx.fillStyle = 'red';

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

ctx.fill();

// 繪制第二個(gè)圓

ctx.beginPath();

ctx.fillStyle = 'blue';

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

ctx.fill();

// 繪制第三個(gè)圓

ctx.beginPath();

ctx.fillStyle = 'green';

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

ctx.fill();

// 繪制第四個(gè)圓

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();

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

圖20  沒(méi)有使用clip方法的4個(gè)圓

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

 

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

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

 

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

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

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

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

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

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

例22  采用clip實(shí)現簡(jiǎn)單的探照燈效果。

<!DOCTYPE html>

<head>

<title>簡(jiǎn)單探照燈</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 隸書(shū)";

        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>

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

 

圖25  簡(jiǎn)單的探照燈

3.圖形變換

在圖形學(xué)中,可以對圖形進(jìn)行平移、縮放和旋轉等變換操作。

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

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

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

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

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);                      // 按矩陣進(jìn)行變換

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

3.1  save和restore方法

       save方法用于保存上下文環(huán)境,restore方法用于恢復到上一次保存的上下文環(huán)境。

       在Canvas中,每個(gè)上下文對象都包含一個(gè)繪圖狀態(tài)的堆,繪圖狀態(tài)包含下列內容:

(1)當前的變換矩陣;

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

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

例23  save方法和restore方法的簡(jiǎn)單應用示例。

     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);

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

 

圖26  4個(gè)矩形

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

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

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

3.2  translate、scale和rotate方法

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

例24  translate簡(jiǎn)單應用示例。

      ctx.fillStyle = "red";

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

      ctx.fillStyle = "blue";

      ctx.translate(80,80);

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

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

 

圖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);

      }

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

圖29  坐標平移后的5個(gè)矩形

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

例26  scale簡(jiǎn)單應用示例。

    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);

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

 

圖30  矩形的縮放

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

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

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

例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);

     }

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

 

圖32  依次放大后的4個(gè)矩形

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

例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);

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

  

圖33  順時(shí)針旋轉了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);

      }

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

圖34  旋轉的矩形

3.3  transform 和setTransform方法

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

a      水平縮放繪圖

b     水平傾斜繪圖

c      垂直傾斜繪圖

d     垂直縮放繪圖

e      水平移動(dòng)繪圖

f      垂直移動(dòng)繪圖

通過(guò)transform() 方法可以縮放、旋轉、移動(dòng)并傾斜當前的繪圖環(huán)境。

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

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

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

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

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

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

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

        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);

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

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

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

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

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

例31  通過(guò)變換繪制螺旋。

   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();

   }

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

 

圖37  螺旋圖

4.圖像處理

       canvas更有意思的一項特性就是圖像操作能力??梢杂糜趧?dòng)態(tài)的圖像合成或者作為圖形的背景,以及游戲界面等等。瀏覽器支持的任意格式的外部圖片都可以使用,比如PNG、GIF或者JPEG。

4.1  圖像繪制

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

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

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

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

// 在畫(huà)布上定位圖像,并規定圖像的寬度和高度

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

 // 剪切圖像,并在畫(huà)布上定位被剪切的部分。

其中,各參數的說(shuō)明如下:

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

sx        可選。開(kāi)始剪切的 x 坐標位置。

sy        可選。開(kāi)始剪切的 y 坐標位置。

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

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

x         在畫(huà)布上放置圖像的 x 坐標位置。

y         在畫(huà)布上放置圖像的 y 坐標位置。

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

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

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

(1)HTMLImageElement。

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

(2)HTMLVideoElement。

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

(3)HTMLCanvasElement。

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

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

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

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

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

例32  在畫(huà)布中繪制頁(yè)面上的圖片。

<!DOCTYPE html>

<head>

<title>在畫(huà)布中繪制頁(yè)面上的圖片</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>

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

圖38  圖片繪制(一)

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

 

圖39  圖片繪制(二)

      (2)創(chuàng )建圖像。

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

var img = new Image();      //  創(chuàng )建一個(gè)img元素

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

當腳本執行后,圖片開(kāi)始裝載。

由于圖像的載入需要時(shí)間,drawImage方法只能在圖像完全載入后才能調用,因此上面的代碼需要改寫(xiě)??捎胠oad時(shí)間來(lái)保證不會(huì )在加載完畢之前使用這個(gè)圖片。

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

img.onload = function(){

  //  執行drawImage語(yǔ)句

}

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

例33  編寫(xiě)如下的HTML文件內容。

<!DOCTYPE html>

<head>

<title>創(chuàng )建圖像對象使用圖片進(jìn)行繪制</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>

      在瀏覽器中打開(kāi)保存這段HTML代碼的html文件,可以看到在畫(huà)布中出現如圖40所示的頁(yè)面。

 

圖40  創(chuàng )建圖像對象使用圖片進(jìn)行繪制

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

       Data urls 允許用一串 Base64 編碼的字符串的方式來(lái)定義一個(gè)圖片。其優(yōu)點(diǎn)就是圖片內容即時(shí)可用,無(wú)須再到服務(wù)器兜一圈。缺點(diǎn)就是圖像沒(méi)法緩存,圖片大的話(huà)內嵌的 url 數據會(huì )相當的長(cháng)。

4.2  像素級操作

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

       (1)createImageData()方法。

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

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

R - 紅色 (0-255)

G - 綠色 (0-255)

B - 藍色 (0-255)

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

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

      像素值以數組形式存在,由于每個(gè)像素有4條信息,因此數組的大小是 ImageData 對象的4倍??梢允褂?ImageDataObject.data.length獲得數組的大小。

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

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

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

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

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

      (2)putImageData()方法。

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

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

各參數的說(shuō)明如下:

imgData      規定要放回畫(huà)布的 ImageData 對象。

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

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

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

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

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

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

例34  createImageData和putImageData方法的簡(jiǎn)單應用。

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);

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

       (3)getImageData()方法。

       getImageData方法可以用來(lái)讀?。◤椭疲〤anvas的內容,返回一個(gè)ImageData對象,包含了每個(gè)像素的信息。其調用形式為:

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

各參數描述如下:

x         開(kāi)始復制的左上角位置的 x 坐標。

y         開(kāi)始復制的左上角位置的 y 坐標。

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

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

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

       例35  通過(guò)操作像素數組的值來(lái)操作圖像。

<!DOCTYPE html>

<head>

<title>通過(guò)操作像素數組的值來(lái)操作圖像</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>

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

圖41  通過(guò)操作像素數組的值來(lái)操作圖像的示例

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

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
<font style="vertical-align: inherit;"><font style="vertical-align: inherit;
HTML5中Canvas(繪制)使用例子 | 一聚教程網(wǎng)
HTML5基礎,第4部分:點(diǎn)睛之筆Canvas
canvas畫(huà)布
HTML5 Canvas標簽使用收錄
canvas
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久