H5的canvas繪圖技術

小周sri的碼農發表於2017-09-12

canvas元素是HTML5中新新增的一個元素,該元素是HTML5中的一個亮點。Canvas元素就像一塊畫布,通過該元素自帶的API結合JavaScript程式碼可以繪製各種圖形和影象以及動畫效果。

 

1.1 瀏覽器不相容問題

  • ie9以上才支援canvas, 其他chromefirefox、蘋果瀏覽器等都支援
  •  只要瀏覽器相容canvas,那麼就會支援絕大部分api(個別最新api除外)
  •  移動端的相容情況非常理想,基本上隨便使用
  •  2d的支援的都非常好,3dwebglie11才支援,其他都支援
  •  如果瀏覽器不相容,最好進行友好提示,提示內容只有在瀏覽器不支援時才顯示。
 //例如:
<canvas id="cavsElem">
        你的瀏覽器不支援canvas,請升級瀏覽器
    </canvas>

 瀏覽器不相容,也可以使用flash等手段進行優雅降級

1.2 建立畫布

在頁面中建立canvas元素與建立其他元素一樣,只需要新增一個<canvas>標記即可。該元素預設的寬高為300*15,可以通過元素的width屬性和height屬性改變預設的寬高。

注意:

  •  不能使用CSS樣式控制canvas元素的寬高,否則會導致繪製的圖形拉伸。

 

  • 重新設定canvas標籤的寬高屬性會導致畫布擦除所有的內容。

 

  • 可以給canvas畫布設定背景色

1.3 canvas座標系

在開始繪製任何影象之前,我們先講一下canvas的座標系。canvas座標系是以左上角0,0處為座標原點,水平方向為x軸,向右為正;垂直方向為y軸,向下為正。如下圖所示:

1.4 繪製線徑

  1. 獲取上下文物件(CanvasRenderingContext2D)

首先,獲取canvas元素,然後呼叫元素的getContext(“2d”)方法,該方法返回一個CanvasRenderingContext2D物件,使用該物件就可以在畫布上繪圖了。

 

var mcanvas  = document.getElementById("mcanvas");
var mcontext = mcanvas.getContext("2d");

  2.設定繪製起點(moveTo)

//語法:
ctx.moveTo(x, y); 

* 解釋:設定上下文繪製路徑的起點。相當於移動畫筆到某個位置。

* 引數:x,y 都是相對於 canvas座標系的原點(左上角)。

* 注意: 繪製線段前必須先設定起點,不然繪製無效。如果不進行設定,就會使用lineTo的座標當作moveTo

3.繪製直線(lineTo)

//語法:
ctx.lineTo(x, y);

* 解釋:從上一步設定的繪製起點繪製一條直線到(x, y)點。

* 引數:x,y 目標點座標。

4.路徑的開始和閉合

//開始路徑:
ctx.beginPath();
//閉合路徑:
ctx.closePath();

* 解釋:如果繪製路徑比較複雜,必須使用路徑開始和結束。閉合路徑會自動把最後的線頭和開始的線頭連在一起。

* beginPath: 核心的作用是將不同繪製的形狀進行隔離,每次執行此方法,表示重新繪製一個路徑,跟之前的繪製的墨跡可以進行分開樣式設定和管理。

5.繪製圖形(stroke)

//語法:
ctx.stroke();

* 解釋:根據路徑繪製線。路徑只是草稿,真正繪製線必須執行stroke

 

在繪製之前,還可以對畫筆的顏色和粗細進行設定進行設定,方法如下:

//語法:
ctx.strokeStyle = “#ff0000”;
ctx.lineWidth = 4;  //值為不帶單位的數字,並且大於0

6.填充圖形(fill)

//語法:
ctx.fill();

* 解釋:對已經畫好的圖形進行填充顏色。

 

在填充之前,同樣可以對所填充的顏色進行設定,方法如下:

//語法:
ctx.fileStyle = “#0000ff”;

7.canvas繪製的基本步驟:

 

第一步:獲得上下文 =>canvasElem.getContext('2d');

 

第二步:開始路徑規劃 =>ctx.beginPath()

 

第三步:移動起始點 =>ctx.moveTo(x, y)

 

第四步:繪製線(線條、矩形、圓形、圖片...) =>ctx.lineTo(x, y)

 

第五步:閉合路徑 =>ctx.closePath();

 

第六步:繪製描邊 =>ctx.stroke();

 

案例:通過上面所學的方法繪製一個三角形。

    <canvas id="mcanvas">你的瀏覽器不支援canvas,請升級瀏覽器</canvas>
    <script>
        
        var mcanvas  = document.getElementById("mcanvas");    //獲得畫布

        var mcontext = mcanvas.getContext("2d");    //獲得上下文

        mcanvas.width = 900;     //重新設定標籤的屬性寬高
        mcanvas.height = 600;    //千萬不要用 canvas.style.height

        mcanvas.style.border = "1px solid #000";    //設定canvas的邊

        //繪製三角形
        mcontext.beginPath();        //開始路徑
        mcontext.moveTo(100,100);    //三角形,左頂點
        mcontext.lineTo(300, 100);   //右頂點
        mcontext.lineTo(300, 300);   //底部的點
        mcontext.closePath();        //結束路徑
        mcontext.stroke();           //描邊路徑

    </script>

案例:理解canvas基於狀態的繪圖

 

<canvas id="mcanvas">你的瀏覽器不支援canvas,請升級瀏覽器</canvas>
    <script>
        
        var mcanvas  = document.getElementById("mcanvas");    //獲得畫布

        var mcontext = mcanvas.getContext("2d");    //獲得上下文

 

mcanvas.width = 900;     //重新設定標籤的屬性寬高
        mcanvas.height = 600;    //千萬不要用 canvas.style.height

        mcanvas.style.border = "1px solid #000";    //設定canvas的邊

        mcontext.strokeStyle = "#ff0000";    //設定畫筆的顏色
        mcontext.lineWidth = 2;                //設定畫筆的粗細
        mcontext.fillStyle = "#00ff00";        //設定填充圖形的顏色

        //繪製三角形
        mcontext.beginPath();        //開始路徑
        mcontext.moveTo(100,100);    //三角形,左頂點
        mcontext.lineTo(300, 100);   //右頂點
        mcontext.lineTo(300, 300);   //底部的點
        mcontext.closePath();        //結束路徑
           mcontext.stroke();           //描邊路徑       
        //mcontext.fill();             //填充圖形

        //繪製矩形
        mcontext.beginPath();    //開啟了一個新狀態(新線徑),
                              //新狀態可以繼承之前狀態的樣式,
                              //但是當前狀態設定的所有樣式只能用於當前狀態。
       
 //mcontext.strokeStyle = "#00ff00";//為當前狀態設定的樣式
        mcontext.moveTo(500,100);    //起始點
        mcontext.lineTo(800,100);    //上邊
        mcontext.lineTo(800,300);    //右邊
        mcontext.lineTo(500,300);    //下邊
        mcontext.closePath();
        mcontext.stroke();

1.5 繪製矩形

  1. 快速建立矩形rect()方法

 

語法:ctx.rect(x, y, width, height);

 

* 解釋:x, y是矩形左上角座標, widthheight都是以畫素計

* rect方法只是規劃了矩形的路徑,並沒有填充和描邊。

2.建立描邊矩形

 

 

 

語法:ctx.strokeRect(x, y, width, height);

 

引數跟rect(x, y, width, height)相同,注意此方法繪製完路徑後立即進行stroke繪製。

3.建立填充矩形

語法:ctx.fillRect(x, y, width, height);

引數跟rect(x, y, width, height)相同, 此方法執行完成後,立即對當前矩形進行fill填充。

4.清除矩形(clearReact

 

語法:ctx.clearRect(x, y, width, hegiht);

 

* 解釋:清除某個矩形內的繪製的內容,相當於橡皮擦。

 

<canvas id="mcanvas">你的瀏覽器不支援canvas,請升級瀏覽器</canvas>
    <script>
        
        var mcanvas  = document.getElementById("mcanvas");    //獲得畫布

        var mcontext = mcanvas.getContext("2d");    //獲得上下文

        mcanvas.width = 900;     //重新設定標籤的屬性寬高
        mcanvas.height = 600;    //千萬不要用 canvas.style.height

        //rect方法只是規劃了矩形的路徑,並沒有填充和描邊,需要單獨描邊或填充。
        mcontext.rect(20,20,300,200);
        mcontext.stroke();

        //快速建立一個描邊的矩形
        mcontext.strokeRect(400,20,300,200);

        //快速建立一個填充的矩形
        mcontext.fillRect(20,300,300,200);

        //在畫布上建立一個矩形區域,該矩形區域中的圖形都會被清除
        mcontext.clearRect(120,350,100,100);

    </script>

1.6 繪製圓形

arc() 方法用於建立弧線(用於建立圓或部分圓)。

 

語法:ctx.arc(x, y, r, startAngle, endAngle, counterclockwise);

 

解釋:
x,y:圓心座標。
r:半徑大小。
sAngle:繪製開始的角度。 圓心到最右邊點是0度,順時針方向弧度增大。
eAngel:結束的角度,注意是弧度。
counterclockwise:是否是逆時針,預設是false。true是逆時針,false:順時針

注意:弧度和角度的轉換公式: rad = deg*Math.PI/180;

繪製圓形和餅圖

<canvas id="mcanvas">你的瀏覽器不支援canvas,請升級瀏覽器</canvas>
    <script>
        
        var mcanvas  = document.getElementById("mcanvas");    //獲得畫布
        var mcontext = mcanvas.getContext("2d");    //獲得上下文
        mcanvas.width = 900;     
        mcanvas.height = 600;  

        //繪製圓形  
        mcontext.beginPath();
        mcontext.arc(200,200,100,0,360*Math.PI/180);
        mcontext.closePath();
        mcontext.stroke();

        // 通過資料進行繪製餅圖
        var data = [{
            "value": .2,
            "color": "red",
            "title": "應屆生"
        },{
            "value": .3,
            "color": "blue",
            "title": "社會招生"
        },{
            "value": .4,
            "color": "green",
            "title": "老學員推薦"
        },{
            "value": .1,
            "color": "#ccc",
            "title": "公開課"
        }];

        var tempAngle = -90;
        var x0 = 600, y0 = 300;
        var raduis = 200;

        for(var i = 0; i < data.length; i++) {
            mcontext.beginPath();
            mcontext.moveTo(x0, y0);
            var angle = data[i].value * 360;
            var startAngle = tempAngle*Math.PI/180;
            var endAngle  = (tempAngle+angle)*Math.PI/180;
            mcontext.fillStyle = data[i].color;
            mcontext.arc(x0, y0, raduis, startAngle, endAngle);
            mcontext.closePath();
            mcontext.fill();
            tempAngle += angle;
        }

    </script>

三角函式的補充:

Math.sin(弧度); //夾角對面的邊 和 斜邊的比值

Math.cos(弧度); //夾角側邊與斜邊的比值

圓形上面的點的座標的計算公式

x =x0 + Math.cos(rad) * R;//x0y0是圓心點座標

y =y0 + Math.sin(rad) * R;//注意都是弧度 

1.7 繪製文字

canvas 提供了兩種方法來渲染文字:

 

fillText(text, x, y [, maxWidth])

 

在指定的(x,y)位置填充指定的文字,繪製的最大寬度是可選的.

 

strokeText(text, x, y [, maxWidth])

 

在指定的(x,y)位置繪製文字邊框,繪製的最大寬度是可選的.

 

示例1

 

文字用當前的填充方式被填充:

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

 ctx.font = "48px serif";
 ctx.fillText("Hello world", 10, 50);

示例2

文字用當前的邊框樣式被繪製:

 var ctx = document.getElementById('canvas').getContext('2d');
  ctx.font = "48px serif";
  ctx.strokeText("Hello world", 10, 50);

文字樣式

font = value: 當前我們用來繪製文字的樣式. 這個字串使用和 CSS font 屬性相同的語法. 預設的字型是 10px sans-serif

textAlign = value: 文字對齊選項. 可選的值包括:start, end, left, right or center. 預設值是 start

 

textBaseline = value:  基線對齊選項. 可選的值包括:top, hanging, middle, alphabetic, ideographic, bottom。預設值是 alphabetic

 

程式碼示例:

<canvas id="mcanvas">你的瀏覽器不支援canvas,請升級瀏覽器</canvas>
    <script>
        
        var mcanvas  = document.getElementById("mcanvas");    //獲得畫布
        var mcontext = mcanvas.getContext("2d");    //獲得上下文
        mcanvas.width = 900;     
        mcanvas.height = 600;  

        mcontext.fillStyle = "#0000ff";
        mcontext.font = "italic 30px 微軟雅黑";
        mcontext.textAlign = "start";
        mcontext.textBaseline = "top";
        mcontext.fillText("你好", 200, 0, 100);

        mcontext.font = "italic 30px 微軟雅黑";
        mcontext.textAlign = "left";
        mcontext.textBaseline = "top";
        mcontext.fillText("你好", 200, 50, 100);

        mcontext.font = "bold 30px 黑體";
        mcontext.textAlign = "center";
        mcontext.textBaseline = "top";
        mcontext.strokeText("你好", 200, 100, 100);

        mcontext.font = "bold 30px 黑體";
        mcontext.textAlign = "right";
        mcontext.textBaseline = "top";
        mcontext.strokeText("你好", 200, 150, 100);

        mcontext.font = "bold 30px 黑體";
        mcontext.textAlign = "end";
        mcontext.textBaseline = "top";
        mcontext.strokeText("你好", 200, 200, 100);

    </script>

1.8繪製影象

1.基本繪製圖片的方式

 

context.drawImage(img,x,y);

 

引數說明: x,y 繪製圖片左上角的座標, img是繪製圖片的dom物件。

2.在畫布上繪製影象,並規定影象的寬度和高度

context.drawImage(img,x,y,width,height);  

引數說明:width 繪製圖片的寬度,  height:繪製圖片的高度

如果指定寬高,最好成比例,不然圖片會被拉伸

設定高 = 原高度 * 設定寬/ 原寬度;

3.圖片裁剪,並在畫布上定位被裁剪的部分

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

引數說明:

    sx,sy 裁剪的左上角座標,

    swidth:裁剪圖片的高度。 sheight:裁剪的高度

其他同上

4.javascript建立img物件

 

上面提供的3個方法,都需要一個Image物件作為引數,下面介紹了幾種建立Image物件的方式。需要注意的是,為Imagesrc屬性賦值後,Image物件會去裝載指定圖片,但這種裝載是非同步的,如果圖片太大或則圖片來自網路,且網路傳輸速度慢,Image物件裝載圖片就會需要:一定的時間開銷。為了保證圖片裝載完成後才去繪製圖片,可以監聽Image物件的onload回撥事件,然後在事件處理函式中繪製圖片,如下所示:

 

第一種方式:

  var img = document.getElementById("imgId");
    img.onload = function(){  //圖片載入完成後,執行此方法
      mcontext.drawImage(img, 10, 10);
    }

第二種方式:

var img = document.createElement("img");
        img.src = "img/a.jpg";
        img.alt = "誰笑誰是小狗";
        img.onload = function(){  //圖片載入完成後,執行此方法
            mcontext.drawImage(img, 10, 10);
        }

第三種方式:

var img = new Image();//這個就是 img標籤的dom物件
    img.src = "imgs/arc.gif";
    img.alt = "誰笑誰是小狗";
    img.onload = function() {  //圖片載入完成後,執行此方法
        
    }

 

相關文章