H5的canvas繪圖技術
canvas元素是HTML5中新添加的一個元素,該元素是HTML5中的一個亮點。Canvas元素就像一塊畫布,通過該元素自帶的API結合JavaScript代碼可以繪制各種圖形和圖像以及動畫效果。
1.1 瀏覽器不兼容問題
- ie9以上才支持canvas, 其他chrome、firefox、蘋果瀏覽器等都支持
- 只要瀏覽器兼容canvas,那么就會支持絕大部分api(個別最新api除外)
- 移動端的兼容情況非常理想,基本上隨便使用
- 2d的支持的都非常好,3d(webgl)ie11才支持,其他都支持
- 如果瀏覽器不兼容,最好進行友好提示,提示內容只有在瀏覽器不支持時才顯示。
//例如: <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 繪制線徑
- 獲取上下文對象(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 繪制矩形
- 快速創建矩形rect()方法
語法:ctx.rect(x, y, width, height);
* 解釋:x, y是矩形左上角坐標, width和height都是以像素計
* 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;//x0和y0是圓心點坐標
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對象的方式。需要注意的是,為Image的src屬性賦值后,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() { //圖片加載完成后,執行此方法 }