<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    我的家園

    我的家園

    HTML5 canvas 元素詳細(xì)教程二

    Posted on 2012-04-15 16:37 zljpp 閱讀(156) 評(píng)論(0)  編輯  收藏

    HTML5 canvas 元素詳細(xì)教程二繪制圖形。

    \" src=在開始之前,我們需要對(duì)canvas 的網(wǎng)格(grid)或者坐標(biāo)空間(coordinate space)進(jìn)行探討。在HTML5 canvas 元素詳細(xì)教程一中有一個(gè)150像素寬, 150像素高的 canvas 對(duì)象的HTML模板。在畫面上疊加上默認(rèn)網(wǎng)格,如右圖。通常網(wǎng)格的1個(gè)單元對(duì)應(yīng) canvas 上的1個(gè)像素。網(wǎng)格的原點(diǎn)是定位在左上角(坐標(biāo)(0,0))。畫面里的所有物體的位置都是相對(duì)這個(gè)原點(diǎn)。這樣,左上角的藍(lán)色方塊的位置就是距左邊x像素和距上邊Y像素(坐標(biāo)(x, y))。現(xiàn)在我們使用默認(rèn)的狀態(tài)來進(jìn)行圖形的繪制吧。

    矩形 Rectangles

            首先來詳細(xì)介紹矩形的繪制吧,矩形有三個(gè)函數(shù)可以繪制的:

    fillRect(x,y,width,height) : Draws a filled rectangle
    strokeRect(x,y,width,height) : Draws a rectangular outline
    clearRect(x,y,width,height) : Clears the specified area and makes it fully transparent

            上面的函數(shù)都接受四個(gè)參數(shù),X和Y用于指定矩形左上角也就是相對(duì)于原點(diǎn)的位置,width和height用于指定矩形的寬和高。這對(duì)于有基礎(chǔ)的同學(xué),還是非常簡(jiǎn)單的。下面,我們使用HTML5 canvas 元素詳細(xì)教程一里提供的 draw() 函數(shù),我們添加了上面的三個(gè)函數(shù)。

    繪制矩形的例子 Rectangular shape example

            運(yùn)行的結(jié)果應(yīng)該和右邊圖形一模一樣的。fillRect 函數(shù)畫了100x100黑色矩形,clearRect 函數(shù)清空了中間 60x60 大小的方塊,然后strokeRect 函數(shù)又在清空了的空間畫出了一個(gè) 50x50 的矩形邊框。。

    繪制路徑 Drawing paths

            繪制路徑不像繪制矩形那要,需要一些額外的步驟,下面是需要使用的函數(shù)和步驟:

    beginPath()
    closePath()
    stroke()
    fill()

            第一步:用 beginPath 創(chuàng)建路徑。在在內(nèi)存中,徑路是以一組子路徑(直線,弧線等)的形式儲(chǔ)存的,它們共同構(gòu)成一個(gè)圖形。每次調(diào)用 beginPath,子路徑組都會(huì)被重置,然后可以繪制新的圖形。

            第二步:是實(shí)際繪制路徑的部分,很快我們就會(huì)看到。

            第三步:調(diào)用 closePath 方法,它會(huì)嘗試用直線連接當(dāng)前端點(diǎn)與起始端點(diǎn)來關(guān)閉路徑,但如果圖形已經(jīng)關(guān)閉或者只有一個(gè)點(diǎn),它會(huì)什么都不做。這一步不是必須的。

            第四部:也就是最后一步,調(diào)用 stroke或 fill 方法,這時(shí),圖形才是實(shí)際的繪制到 canvas上去。stroke是繪制圖形的邊框,fill會(huì)用填充出一個(gè)實(shí)心圖形。當(dāng)調(diào)用 fill 時(shí),開放的路徑會(huì)自動(dòng)閉合,而無須調(diào)用 closePath ,這需要大家注意。

    畫一個(gè)簡(jiǎn)單圖形(如三角形)的代碼如下。

    ctx.beginPath();
    ctx.moveTo(75,50);
    ctx.lineTo(100,75);
    ctx.lineTo(100,25);
    ctx.fill();
     

            moveTo 是一個(gè)十分有用的方法,它是繪制路徑的實(shí)用方法的一部分。你可以把它想象成是把筆提起,并從一個(gè)點(diǎn)移動(dòng)到另一個(gè)點(diǎn)的過程。

    moveTo(x, y)

            它接受 x 和 y (新的坐標(biāo)位置)作為參數(shù)。

            當(dāng)進(jìn)行 canvas 初始化或者調(diào)用 beginPath 的時(shí)候,起始坐標(biāo)設(shè)置就是原點(diǎn)(0,0)。許多的情況下,我 moveTo 方法將起始坐標(biāo)移至其它地方,或者用于繪制不連續(xù)的路徑。看看右邊的笑臉,紅線就是使用 moveTo 移動(dòng)的軌跡。

            把下面的moveTo 的使用示例代碼粘貼到之前用過的 draw 函數(shù)內(nèi)在看看效果吧。

    ctx.beginPath();
    ctx.arc(75,75,50,0,Math.PI*2,true); // Outer circle
    ctx.moveTo(110,75);
    ctx.arc(75,75,35,0,Math.PI,false);   // Mouth (clockwise)
    ctx.moveTo(65,65);
    ctx.arc(60,65,5,0,Math.PI*2,true);  // Left eye
    ctx.moveTo(95,65);
    ctx.arc(90,65,5,0,Math.PI*2,true);  // Right eye
    ctx.stroke();

    //thegoneheart 完整例子

    ctx.beginPath();
    ctx.arc(75,75,50,0,Math.PI*2,true); // Outer circle
    ctx.moveTo(110,75);
    ctx.arc(75,75,35,0,Math.PI,false);   // Mouth (clockwise)
    ctx.moveTo(65,65);
    ctx.arc(60,65,5,0,Math.PI*2,true);  // Left eye
    ctx.moveTo(95,65);
    ctx.arc(90,65,5,0,Math.PI*2,true);  // Right eye
    ctx.stroke();
                           
    ctx.beginPath();
    ctx.moveTo(40,75);
    ctx.lineTo(60,65);
    ctx.lineTo(90,65);
    ctx.moveTo(110,75);
    ctx.lineTo(125,75);
    ctx.stroke();
         

    注意:你可以注釋 moveTo 方法來觀察那些連接起來的線。
    注意:arc 方法的用法見下面。

    繪制各種線條 Lines

            在這里使用lineTo 方法來畫直線。lineTo 方法接受終點(diǎn)的坐標(biāo)(x,y)作為參數(shù)。起始坐標(biāo)取決于前一路徑,前一路徑的終點(diǎn)即當(dāng)前路徑的起點(diǎn),起始坐標(biāo)也可以通過 moveTo 方法來設(shè)置。

    lineTo(x, y)

    lineTo 的使用示例

            示例(如右圖)畫的是兩個(gè)三角形,一個(gè)實(shí)色填充,一個(gè)勾邊。首先調(diào)用 beginPath 方法創(chuàng)建一個(gè)新路徑,然后用moveTo 方法將起始坐標(biāo)移至想要的位置,然后畫兩條直線來構(gòu)成三角形的兩條邊。

            可以注意到 fill 和 strok 繪三角形的區(qū)別,使用 fill 路徑會(huì)自動(dòng)閉合,但使用 stroke 不會(huì),如果不關(guān)閉路徑,勾畫出來的只有兩邊。

    //填充三角形
    ctx.beginPath();
    ctx.moveTo(25,25);
    ctx.lineTo(105,25);
    ctx.lineTo(25,105);
    ctx.fill();

    // 勾邊三角形
    ctx.beginPath();
    ctx.moveTo(125,125);
    ctx.lineTo(125,45);
    ctx.lineTo(45,125);
    ctx.closePath();
    ctx.stroke(); 
       

    弧線 Arcs

    arc 方法是來繪制弧線或圓。

    arc(x, y, radius, startAngle, endAngle, anticlockwise)
    arc(x, y, radius, startAngle, endAngle, anticlockwise)

    該方法接受五個(gè)參數(shù): 1、,y 是圓心坐標(biāo);
    2、radius 是半徑;
    3、startAngle是起弧度(以 x 軸為基準(zhǔn));
    4、endAngle 是末弧度(以 x 軸為基準(zhǔn));
    5、anticlockwise 為 true 表示逆時(shí)針,反之順時(shí)針。

            警告:在 Firefox 的 beta 版本里,最后一個(gè)參數(shù)是 clockwise,而最終版本不是。因此如果是從 beta 升級(jí)至發(fā)行版需要做相應(yīng)修改。

            注意:arc 方法里用到的角度是以弧度為單位而不是度。度和弧度直接的轉(zhuǎn)換可以用這個(gè)表達(dá)式:var radians = (Math.PI/180)*degrees;。

    arc 的使用示例

            這個(gè)示例比之前見到過的要復(fù)雜一些,畫了12個(gè)不同的弧形,有不同夾角和填充狀態(tài)的。如果我用上面畫笑臉的方式來畫這些弧形,那會(huì)是一大段的代碼,而且,畫每一個(gè)弧形時(shí)我都需要知道其圓心位置。像我這里畫 90,180 和 270 度的弧形看起來不是很麻煩,但是如果圖形更復(fù)雜一些,則實(shí)現(xiàn)起來會(huì)越來越困難。

            這里使用兩個(gè) for 循環(huán)來畫多行多列的弧形。每一個(gè)弧形都用 beginPath 方法創(chuàng)建一個(gè)新路徑。然后為了方便閱讀和理解,我把所有參數(shù)都寫成變量形式。顯而易見,x 和 y 作為圓心坐標(biāo)。 radius  startAngle 都是固定,endAngle 從 180 度半圓開始,以 90 度方式遞增至圓。anticlockwise 則取決于奇偶行數(shù)。

        for (i=0;i<4;i++){
        for(j=0;j<3;j++){    //chinese_xu 原始代碼
        ctx.beginPath();
        var x              = 25+j*50;               // x coordinate
        var y              = 25+i*50;               // y coordinate
        var radius         = 20;                    // Arc radius
        var startAngle     = 0;                     // Starting point on circle
        var endAngle       = Math.PI+(Math.PI*j)/2;  // End point on circle ---//修復(fù)錯(cuò)誤標(biāo)點(diǎn)
        var anticlockwise  = i%2==0 ? false : true; // clockwise or anticlockwise

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

        if (i>1){
          ctx.fill();
        } else {
          ctx.stroke();
        }
      }
    }
    //chinese_xu 原始代碼并沒有按照1/4圓遞增來畫。


    //修改后輸出4行4列,要把畫布擴(kuò)大到200*200觀看
    for (i=0;i<4;i++){
       for(j=0;j<4;j++){    
        ctx.beginPath();
        var x              = 25+j*50;               // x coordinate
        var y              = 25+i*50;               // y coordinate
        var radius         = 20;                    // Arc radius
        var startAngle     = 0;                     // Starting point on circle
        var endAngle       = Math.PI*(2-j/2);   // End point on circle
        var anticlockwise  = i%2==0 ? false : true; // clockwise or anticlockwise

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

        if (i>1){
          ctx.fill();
        } else {
          ctx.stroke();
        }
      }
    }
         

    貝塞爾和二次方曲線 Bezier and quadratic curves

            貝塞爾曲線可以是二次和三次方的形式,常用于繪制復(fù)雜而有規(guī)律的形狀。

    quadraticCurveTo(cp1x, cp1y, x, y)
    bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

            兩行代碼的區(qū)別見右圖。它們都是一個(gè)起點(diǎn)一個(gè)終點(diǎn)(圖中的藍(lán)點(diǎn)),但二次方貝塞爾曲線只有一個(gè)(紅色)控制點(diǎn)點(diǎn))而三次方貝塞爾曲線有兩個(gè)。

            參數(shù) x 和 y 是終點(diǎn)坐標(biāo),cp1x  cp1y 是第一個(gè)控制點(diǎn)的坐標(biāo),cp2x  cp2y 是第二個(gè)的。

            使用二次方和三次方的貝塞爾曲線是相當(dāng)有挑戰(zhàn)的,因?yàn)椴幌裨谑噶坷L圖軟件 Adobe Illustrator 里那樣有即時(shí)的視覺反饋。因?yàn)橛盟鼇懋嫃?fù)雜圖形是比較麻煩的。但如果你有時(shí)間,并且最重要是有耐心,再?gòu)?fù)雜的圖形都可以繪制出來的。下面我們來畫一個(gè)簡(jiǎn)單而又規(guī)律的圖形。

            這些例子都比較簡(jiǎn)單。我們繪制的都是完整的圖形。

    quadraticCurveTo 的使用示例

    // Quadratric curves example
    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();

            通過計(jì)算,可以由二次曲線的單個(gè)控制點(diǎn)得出相應(yīng)三次方曲線的兩個(gè)控制點(diǎn),因此二次方轉(zhuǎn)三次方是可能的,但是反之不然。僅當(dāng)三次方程中的三次項(xiàng)為零是才可能轉(zhuǎn)換為二次的貝塞爾曲線。通常地可以用多條二次方曲線通過細(xì)分算法來近似模擬三次方貝塞爾曲線。

    bezierCurveTo 的使用示例

    			// Bezier curves example
    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();
          
     

    矩形路徑 Rectangles

            除了上面提到的三個(gè)方法可以直接繪制矩形之外,我們還有一個(gè) rect 方法是用于繪制矩形路徑的。

    rect(x, y, width, height)

            它接受四個(gè)參數(shù),x  y 是其左上角坐標(biāo),width  height 是其寬和高。

            當(dāng)它被調(diào)用時(shí),moveTo 方法會(huì)自動(dòng)被調(diào)用,參數(shù)為(0,0),于是起始坐標(biāo)又恢復(fù)成初始原點(diǎn)了。

    綜合 Making combinations

            我們上面的示例都只用到了一種類型的路徑,當(dāng)然 canvas 不會(huì)限制所使用的路徑類型的多少。

    綜合樣例

            在整個(gè)例子里,最值得注意的是 roundedRect 函數(shù)的使用和 fillStyle 屬性的設(shè)置。自定義函數(shù)對(duì)于封裝復(fù)雜圖形的繪制是非常有用的。在這個(gè)例子里使用自定義函數(shù)就省掉了大約一半的代碼。

            在接下來的例子里會(huì)深入探討 fillStyle 屬性的使用。這里是用它來改變填充顏色,從默認(rèn)的黑色,到白色,然后再回到黑色。

      function draw() {
      var ctx = document.getElementById('canvas').getContext('2d');
      roundedRect(ctx,12,12,150,150,15);
      roundedRect(ctx,19,19,150,150,9);
      roundedRect(ctx,53,53,49,33,10);
      roundedRect(ctx,53,119,49,16,6);
      roundedRect(ctx,135,53,49,33,10);
      roundedRect(ctx,135,119,25,49,10);

      ctx.beginPath();
      ctx.arc(37,37,13,Math.PI/7,-Math.PI/7,false); //chiensexu  本來是true呵呵,反了
      ctx.lineTo(31,37);
      ctx.fill();
      for(i=0;i<8;i++){
        ctx.fillRect(51+i*16,35,4,4);
      }
      for(i=0;i<6;i++){
        ctx.fillRect(115,51+i*16,4,4);
      }
      for(i=0;i<8;i++){
        ctx.fillRect(51+i*16,99,4,4);
      }
      ctx.beginPath();
      ctx.moveTo(83,116);
      ctx.lineTo(83,102);
      ctx.bezierCurveTo(83,94,89,88,97,88);
      ctx.bezierCurveTo(105,88,111,94,111,102);
      ctx.lineTo(111,116);
      ctx.lineTo(106.333,111.333);
      ctx.lineTo(101.666,116);
      ctx.lineTo(97,111.333);
      ctx.lineTo(92.333,116);
      ctx.lineTo(87.666,111.333);
      ctx.lineTo(83,116);
      ctx.fill();
      ctx.fillStyle = "white";
      ctx.beginPath();
      ctx.moveTo(91,96);
      ctx.bezierCurveTo(88,96,87,99,87,101);
      ctx.bezierCurveTo(87,103,88,106,91,106);
      ctx.bezierCurveTo(94,106,95,103,95,101);
      ctx.bezierCurveTo(95,99,94,96,91,96);
      ctx.moveTo(103,96);
      ctx.bezierCurveTo(100,96,99,99,99,101);
      ctx.bezierCurveTo(99,103,100,106,103,106);
      ctx.bezierCurveTo(106,106,107,103,107,101);
      ctx.bezierCurveTo(107,99,106,96,103,96);
      ctx.fill();
      ctx.fillStyle = "black";
      ctx.beginPath();
      ctx.arc(101,102,2,0,Math.PI*2,true);
      ctx.fill();
      ctx.beginPath();
      ctx.arc(89,102,2,0,Math.PI*2,true);
      ctx.fill();
    }
    function roundedRect(ctx,x,y,width,height,radius){
      ctx.beginPath();
      ctx.moveTo(x,y+radius);
      ctx.lineTo(x,y+height-radius);
      ctx.quadraticCurveTo(x,y+height,x+radius,y+height);
      ctx.lineTo(x+width-radius,y+height);
      ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
      ctx.lineTo(x+width,y+radius);
      ctx.quadraticCurveTo(x+width,y,x+width-radius,y);
      ctx.lineTo(x+radius,y);
      ctx.quadraticCurveTo(x,y,x,y+radius);
      ctx.stroke();
    }


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲AV无码一区二区三区电影| 亚洲丝袜中文字幕| 久草免费福利在线| 久久久精品国产亚洲成人满18免费网站 | 四虎永久在线观看免费网站网址 | 亚洲人色婷婷成人网站在线观看| 最好2018中文免费视频| 亚洲国产一区二区视频网站| www成人免费视频| 亚洲中文字幕无码一区| 毛片在线播放免费观看| 久久精品亚洲中文字幕无码麻豆 | 精品97国产免费人成视频| 亚洲自偷自偷偷色无码中文| 国产精品网站在线观看免费传媒| 亚洲v高清理论电影| 日本高清在线免费| 亚洲aⅴ无码专区在线观看| 免费乱理伦在线播放| 国产在线国偷精品免费看| 亚洲av一综合av一区| 足恋玩丝袜脚视频免费网站| 亚洲乱码在线卡一卡二卡新区| 免费国产高清视频| 中文字幕在线视频免费| 亚洲视频免费观看| 日本免费人成视频播放| 国产一级a毛一级a看免费视频| 亚洲毛片在线免费观看| 国产极品美女高潮抽搐免费网站| xvideos永久免费入口| 亚洲综合无码一区二区三区| 毛片免费全部播放一级| 国产特黄一级一片免费| 亚洲国产精品白丝在线观看| 国产免费69成人精品视频| 99免费观看视频| 免费人成视频在线播放| 亚洲天堂一区二区三区四区| 亚洲精品网站在线观看不卡无广告| 一区二区三区在线免费看 |