HTML5新增核心工具——canvas


Canvas元素稱得上是HTML5的核心所在,它是一個依靠JavaScript繪制華麗圖像的元素。

Canvas由一個可繪制地區HTML代碼中的屬性定義決定高度和寬度,JavaScript代碼可以訪問該地區,通過一套完整的繪圖功能類似於其他通用二維的API,從而生成動態的圖形。

Canvas可以在瀏覽器中繪制出十分華麗的圖形,比如:

當然這應該算比較高級的用法了,本菜也不會=.=

Canvas一個很大的作用就是制作游戲,本文通過博主之前做的一個小游戲來從零介紹Canvas的用法,先展示下吧:

OK,這就是用Canvas來完成的游戲。

 

繪制之前的准備工作:

1.在body中加入canvas標簽,設置它的id、width、height,當然也可以動態設置它的寬高。

 <canvas id="mycanvas" width="1200" height="500"></canvas>

2.獲得canvas對象的上下文obj.getContext(par),par參數為“2d”,目前canvas只支持二維效果。

var ctx = document.getElementById("mycanvas").getContext("2d");

如此你便有了一張1200*500的“畫布”和一支名為“ctx”的畫筆,接下來我們從一些最簡單的圖形開始繪制。

 

繪制矩形:

示例代碼如下:

var ctx=document.getElementById("container").getContext("2d");
    
    ctx.fillStyle="blue";
    ctx.fillRect(10,10,200,100);

    ctx.lineWidth=10;
    ctx.strokeStyle="red";
    ctx.strokeRect(300,10,200,100);

其中fill表示填充,stroke表示僅繪制邊框。

同理fillRect表示實心矩形,strokeRect表示矩形邊框,他們都有四個參數:x,y,w,h 分別為橫縱坐標、寬、高。

fillStyle表示填充樣式,strokeStyle表示邊框樣式。

lineWidth表示線寬。

顯示結果:

需要注意的是,設置樣式等應寫在繪制圖形之前,否則樣式會渲染不上。

在繪制多個圖形時,應該在繪制一個圖形之前開繪制路徑,定制完成后關閉繪制路徑並繪制定制好的圖形。例如上例標准寫法應為:

   var ctx=document.getElementById("container").getContext("2d");
    ctx.beginPath();
    ctx.fillStyle="blue";
    ctx.fillRect(10,10,200,100);
    ctx.closePath();
    ctx.stroke();

    ctx.beginPath();
    ctx.lineWidth=10;
    ctx.strokeStyle="red";
    ctx.strokeRect(300,10,200,100);
    ctx.closePath();
    ctx.stroke();

beginPath()開啟繪制路徑,closePath()閉合繪制路徑,stroke()繪制定制圖形。在之后的練習中一定要養成習慣,否則當繪制線條時就會發現由於未閉合繪制路徑所出現的線條錯連。

 

繪制線條:

示例代碼如下:

var ctx=document.getElementById("container").getContext("2d");
    ctx.beginPath();
    ctx.moveTo(400,100);
    ctx.lineTo(300,200);
    ctx.lineTo(350,200);
    ctx.lineTo(250,300);
    ctx.lineTo(400,300);
    ctx.closePath();
    ctx.stroke();

其中,moveTo表示將畫筆移動到某個坐標上,lineTo指以畫筆落點開始畫到哪個位置。本次我們想要畫一個簡單的樹冠,結果:

可見,這里我們只畫了一半。(400,100)位置為樹頂,(400,300)位置為樹底中部,線條自動閉合正是我們關閉繪制路徑所產生的效果。

接下來我們把另一半畫完,並給這棵樹填充上綠色:

 var ctx=document.getElementById("container").getContext("2d");
    ctx.beginPath();
    ctx.fillStyle="green";
    ctx.moveTo(400,100);
    ctx.lineTo(300,200);
    ctx.lineTo(350,200);
    ctx.lineTo(250,300);
    ctx.lineTo(400,300);
    ctx.lineTo(550,300);
    ctx.lineTo(450,200);
    ctx.lineTo(500,200);
    ctx.lineTo(400,100);
    ctx.fill();
    ctx.closePath();
    ctx.stroke();

注意寫在最后的fill()為填充樣式:

 

繪制圓形:

示例代碼:

 var ctx=document.getElementById("container").getContext("2d");
    ctx.beginPath();
    ctx.arc(200,200,100,0,360*Math.PI/180,true);
    ctx.closePath();
    ctx.stroke();

arc(x,y,r,starta,enda,anti);參數分別代表:圓心橫、縱坐標,半徑、起始角(需轉換成弧度值)、終止角、繪制方向。

用canvas繪制圓,如果你是剛接觸一定覺得很糾結,因為它的參數有很多都是相反的。這里為了大家不糾結,我多羅嗦幾句。

起、止角的計算與我們數學上的角度計算不同,數學中的角度逆時針為正,而這里的起止角是以順時針為正,也就是當你起角設為0度,止角設為120度。它是從右邊水平位置向下旋轉計算角度。

還有就是繪制方向上,true代表逆時針,false代表順時針。暈了的同學看下面的例子:

 ctx.arc(200,200,100,0,120*Math.PI/180,true);

設起角為0,止角120。按數學上的思想應該是一個小於半圓的上半邊的弧,而結果:

這里true表示逆時針繪制,所以繪出了的圖形大於半圓。若改為false:

 

此時順時針繪制出的圖形小於半圓,這里大家應該也可以理解arc的角度計算方向是與數學相反的。要想畫一個位於上方的小半圓?止角設為-120度,繪制方向true即可。

這里羅嗦這么多就是希望剛接觸的朋友們少走彎路,不像我們研究半天。

 

繪制陰影:

 var ctx=document.getElementById("container").getContext("2d");
    ctx.beginPath();
    ctx.fillStyle="gray";
    ctx.shadowOffsetX=5;
    ctx.shadowOffsetY=5;
    ctx.shadowColor="gold";
    ctx.shadowBlur=5;
    ctx.fillRect(10,10,100,100);
    ctx.closePath();
    ctx.stroke();

shadowOffsetX、shadowOffsetY表示陰影橫、縱向偏移量,shadowColor表示陰影顏色,shadowBlur表示模糊等級。

由於在之前CSS3相關博文中已經講了不少關於陰影的東西了,這里就一筆帶過。依然需要注意的是,先設置樣式,最后再繪制矩形,順序反了效果會渲染不上。

 

繪制漸變:

線性漸變:

   ctx.beginPath();
   var Color=ctx.createLinearGradient(500,500,500,0);
   Color.addColorStop(0.3,"orange");
   Color.addColorStop(0.5,"yellow");
   Color.addColorStop(1,"gray");
   ctx.fillStyle=Color;
   ctx.fillRect(0,0,1200,500);
   ctx.closePath();
   ctx.stroke();

寫法為:將ctx.createLinearGradient()賦值給一顏色變量,顏色變量可以添加多個漸變顏色,addColorStop其共有兩個參數,1.偏移量(0-1)2.顏色。最后將顏色變量賦給fillStyle。

createLinearGradient()共有四個參數:1、2表示起始面,3、4表示終於面。

徑向漸變:

   ctx.beginPath();
        ctx.arc(500,300,100,0,360*Math.PI/180,true);
        var Color=ctx.createRadialGradient(500,300,30,500,300,100);
        Color.addColorStop(0,"red");
        Color.addColorStop(0.5,"orange");
        Color.addColorStop(1,"yellow");
        ctx.fillStyle=Color;
        ctx.fill();
        ctx.closePath();
        ctx.stroke();

與線性漸變比較相似,不同的是其名為createRadialGradient()中有六個參數:1、2.漸變開始圓的圓心坐標,3.漸變開始圓的半徑,4、5.漸變結束圓的圓心坐標,6.漸變結束圓的半徑。

 

繪制文字:

ctx.beginPath();
ctx.strokeStyle="gold";
ctx.fillStyle="bule";
ctx.font="50px 微軟雅黑";
ctx.strokeText("hello world!",700,200);
ctx.font="30px 幼圓";
ctx.fillText("hello kitty?",700,300);
ctx.fill();
ctx.closePath();
ctx.stroke();
fillText(text,x,y,[maxwidth])繪制字符串,text表示文字內容,x,y文字坐標位置。[maxwidth]可選,設置字符最大寬度防止溢出。font設置字體。
其它參數:
textAlign 設置文字水平對齊方式 value 為 start|end|left|right|center  默認值為start
textBaseline 設置文字垂直對齊方式 value 為 top|hanging|middle|alphabetic|ideographic|bootom  默認為alphabetic
大家有興趣自己試試吧。
 
圖片繪制:
呼.....寫了半天終於寫到正題了,相對於上面簡單圖形的繪制,圖片繪制要用的更多一些,尤其是在游戲中。
這里介紹一種較簡單的方法,首先在body中寫上:
   <div class="hide">
        <img src="" id="myImg">
   </div>

將你想要繪制的圖片先加入body中,然后將父級div隱藏,一個隱藏的div中可以放入一個項目中所有需要繪制的圖片甚至是音頻文件,就好像一個別人看不見的素材庫。

然后:

 var ctx = document.getElementById("mycanvas").getContext("2d");
    var img=document.getElementById("myImg");
    ctx.beginPath();
    ctx.drawImage(img,x,y);
    ctx.closePath();
    ctx.stroke();

得到你想要繪制的圖片對象,通過drawImage來繪制。這里drawImage()可以有3個參數,5個參數,9個參數。

3個參數:1.需要繪制的圖片對象 2,3.圖片坐標;

5個參數:1.需要繪制的圖片對象 2,3.圖片坐標 4,5.圖片寬高;

9個參數:1.需要繪制的圖片對象 2,3.繪制圖片的橫縱向切割點 4.橫向切割寬度 5.縱向切割高度 6,7.切割好的圖片坐標 8,9.切割好的圖片寬高。

前兩個比較好理解,第三種參數模式怎么用呢?這里舉個例子:在最開始展示的游戲中,會走路的怪物並不是gif,而是如下的背景透明的PNG格式:

我們通過一定的時間間隔截取圖片中不同的區域,連貫起來就成了動畫的效果了。說起切割圖片,學過Web性能優化的人很容易想起 Spirite,它就是通過把一網頁上的所需的圖片全部匯集到一張圖上,用哪部分就截取哪部分。

扯遠了,現在我們試着讓這種綠怪物走起來:

 var ctx=document.getElementById("container").getContext("2d");
    var img=document.getElementById("myImg");
    var X=0;
    var countNum=0;
    function picRun(){
        ctx.clearRect(0,0,1200,1000);
        countNum++;
        if(countNum==10){
            X+=129;
            countNum=0;
        }
        if(X>=387){
            X=0;
        }
        ctx.beginPath();
        ctx.drawImage(img,X,0,129,135,100,100,129,135);
        ctx.closePath();
        ctx.stroke();
    }
    window.setInterval(picRun,30);

*** 首先加入圖片,獲取圖片對象。分析下怪物走路那張圖片,寬為515px,高為135px,也就是說每個單獨的怪物寬為四分之一即129px,高為135px。

將橫向切割點設為變量X,由於此圖只需橫切不需要縱切,縱向切割點設為常量,實際上做法一樣。

在drawImage中填入參數,就本例而言只有橫向切割點一個變量。通過setInterval來循環執行picRun函數,每30毫秒執行一次。countNum俗稱計數器,在做游戲中比較常見,目的是為了控制圖片的切換頻率。

(由於一個游戲中通常有多個動作頻率不同的對象,所以當然不能隨便改變setInterval的執行頻率。加入了計數器,就能很好的控制各個對象的動作頻率了)

本例中圖片切換頻率為30*10即300毫秒一次,切換時橫向切割點右移135px即怪物寬度,當橫向切割點大於3個怪物寬度時回0坐標重新切割。

clearRect()是為了清除之前的圖層,始終只顯示一張圖片,否則每次切出的新圖會不停疊加。

結果:

 

本文到此結束,下篇介紹HTML5另一核心工具——本地存儲,敬請期待。


免責聲明!

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



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