本文重點還是要介紹Canvas,但每次提起Canvas,腦海總會想起SVG,因此先做個簡單的對比。

*Canvas 和 SVG 對比
Canvas 和 SVG 都是 html5 中推薦的也是主要的2D圖形繪制技術(shù)
- Canvas 提供畫布標簽和繪制API,技術(shù)比較新,注重柵格圖像處理。
- SVG是一套獨立的矢量圖形語言,成為W3C標準已經(jīng)有十幾年,發(fā)展緩慢。
- Canvas 基于像素,提供 2D 繪制函數(shù),是一種HTML元素類型,依賴于HTML,只能通過腳本繪制圖案;
- SVG為矢量圖,提供一系列圖形元素(Rect,Path,Circle,Line...);還有完整的動畫,時間機制,本身就能獨立使用,也可以嵌入到HTML中。O
**適用場景
- Canvas 提供功能更原始,動態(tài)渲染和大數(shù)據(jù)量繪制
- 依賴分辨率
- 不支持事件處理器
- 弱的文本渲染能力
- 能夠以.png 或 .jpg 格式保存結(jié)果圖像
- 最適合圖像密集型游戲,其中的許多對象會被頻繁的重繪。
- SVG功能更完善,適合靜態(tài)圖片展示,高保證文檔查看和打印的應(yīng)用場景;
- 不依賴分辨率
- 支持事件處理器
- 最適合帶有大型渲染區(qū)域的應(yīng)用程序(比如谷歌地圖)
- 復(fù)雜度高會減慢渲染速度(任何過度使用 DOM 的應(yīng)用都不快)
- 不適合游戲應(yīng)用
0. 什么是 Canvas
<canvas>是H5新增的組件,就像一塊幕布,一個可以使用腳本(通常為JAVAscript)在其中繪制圖形的HTML元素,他可以用來制作各種圖、表,或者一些動畫。 在沒有<canvas>的年代,繪圖只能借助Flash插件實現(xiàn),需要使用JavaScript和flash交互,現(xiàn)在我們省去了flash,直接使用javascript完成繪制。
1. 創(chuàng)建一個 <canvas>
一個canvas定義了一個指定的矩形框,在這個范圍內(nèi)我們可以隨意繪制html代碼
<canvas id="mycanvas" width="200" height="100"></canvas>
一個使用技巧:在<canvas>內(nèi)部添加一些說明性的<html>代碼,什么作用呢?當(dāng)瀏覽器支持<canvas>的時候,它將忽略<canvas>內(nèi)部的內(nèi)容,如果不支持,它將顯示內(nèi)部的HTML:html代碼
<canvas id="mycanvas" width="200" height="100">
<p>您的瀏覽器不支持Canvas</p>
</canvas>
通過canvas.getContext屬性獲取canvas內(nèi)部內(nèi)容。javascript代碼
window.onload = function () {
var canvas = document.getElementById("mycanvas");
if (canvas.getContext) {
document.write("支持")
}else{
document.write("不支持")
}
}
結(jié)果展示

運行結(jié)果
2. 獲取canvas
- javascript通過id獲取canvas:
var c = document.getElementById("mycanvas");
- 獲得繪制環(huán)境:
一般頁面上繪制的都是2d圖像。所以我們使用的是'2d' 標準。擁有多種繪制路徑,矩形,圓形,字符以及圖像的方法。
var ctx = getContext('2d')
該方法能夠獲取canvasRenderingContext對象,我們所有的操作都需要通過這個對象來完成。注:如果想要繪制3d圖像,請使用WebGL規(guī)范,即
var gl = getContext('webgl');
我們已經(jīng)獲取了canvasRenderingContext2D對象,接下來我們可以在該對象上開始繪制圖形了
3. canvas坐標
我們可以再canvas上繪制各種形狀,在此之前,我們先了解一下坐標系統(tǒng)。

canvas坐標以我們定義的canvas畫布的左上角為起點,水平向右為x軸,豎直向下為Y軸,以像素為單位,所以每個點都是非負整數(shù)。
4. 繪制圖形 - 矩形
我們必須明確知道,canvas元素本身沒有繪圖能力,所有的繪制工作必須在JavaScript內(nèi)部完成公式方法
fillRect(x, y, width, height)
效果先看

canvas繪制一個紅色矩形
html代碼
<canvas id="cv" width="200" height="200"></canvas>
css代碼
* {background-color: #4e4e4e;}
canvas { background-color: white; }
javascript代碼
var c = docuent.getElementById("mycanvas");
var cts = document.getContext("2d");
ctx.fillStyle = "#ff0000";
ctx.fillRect(0,0,150,75);
案例分析 前兩步已經(jīng)解釋過了,fillStyle屬性可以是顏色,漸變,或圖案;默認值是顏色中的黑色#000000。 fillRect(x, y, width, height);注意每個值的意思,別理解成(x1, y1, x2, y2)
5. canvas 繪制路徑 - 線條
canvas畫線,我們使用以下方法:
- moveTo(x, y) - 定義線條的開始位置;
- lineTo(x, y) - 定義線條的結(jié)束位置;
- 繪制線條我們必須使用到 "ink" 的方法,就像stroke().
效果先看

html代碼
<canvas id="cv" width="150" height="150">
<p>您的瀏覽器不支持canvas</p>
</canvas>
javascript代碼
var c=document.getElementById("cv");
var cxt=c.getContext("2d");
cxt.moveTo(20,10);
cxt.lineTo(200,100);
cxt.lineTo(20,100);
cxt.stroke();
css代碼
canvas {
border: solid 1px #000;
padding-left: 100px;
margin-left: 100px;
}
案例分析: 該案例中我故意埋了幾個點:
- 設(shè)置canvas寬度高度不足畫線設(shè)定的起始終或結(jié)束位置,所畫的線并不會超出畫布范圍。
- 設(shè)置padding-left: 100px;, 畫線受內(nèi)邊距影響
- 設(shè)置margin-left: 100px;畫布右偏移了100像素,畫線相對畫布的位置依舊不變。
所以我們得出結(jié)論,無論什么情況下,畫線都只會在畫布內(nèi)部有效。
6. Canvas繪制路徑 - 圓形
Canvas API 也使用了路徑的表示法。但是,路徑由一系列的方法調(diào)用來定義,而不是描述為字母和數(shù)字的字符串,比如調(diào)用 beginPath()和 arc() 方法。 一旦定義了路徑,其他的方法,如fill(),都是對此路徑操作。繪圖環(huán)境的各種屬性,比如 fillStyle,說明了這些操作如何使用。 繪制圓形,公式如下
arc(x, y, r, start, stop); //畫圓 start 和 stop 一般用Math.PI輔助得出
效果先看

在圓心為(70,60)處繪制一個半徑為40的圓
思路
繪制路徑調(diào)用beginPath() 和 closePath() 來描述開始和結(jié)束繪制, 調(diào)用fill()使其生效。
javascript代碼
var c = document.getElementById("cv");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(70, 60, 40, 0, 2*Math.PI);
ctx.closePath();
ctx.fillStyle="pink";
ctx.fill();
7. Canvas繪制圖形 - 綜合案例
在繼續(xù)往下說之前,我想讓大家再看一個復(fù)雜/系統(tǒng)一點的案例,這對我們更深入理解和鞏固canvas繪圖會有很大的幫助效果先看

綜合案例 - 繪制笑臉
html代碼
<canvas id="cv" width="150" height="150"></canvas>
javascript代碼
var c = document.getElementById("cv");
var ctx = c.getContext("2d");
ctx.clearRect(0, 0, 150, 150); // 擦除(0, 0)位置大小為150的矩形,擦除的意思就是把該區(qū)域變得透明
ctx.fillStyle="pink"; // 規(guī)定要填充區(qū)域的顏色(也可以是漸變或圖案)
ctx.fillRect(20, 20, 110, 110); //指定填充的區(qū)域
// 定義路徑,利用Path繪制復(fù)雜的路徑
var path = new Path2D();
path.arc(75, 75, 50, 0, 2*Math.PI, true); // true或false來指定是正向繪制還是反向繪制
path.moveTo(105, 78); // 將繪制筆頭移動到指定坐標
path.arc(75, 78, 30, 0, Math.PI, false); // 此處繪制一個 半圓
path.moveTo(65, 60);
path.arc(60, 60, 5, 0, 2*Math.PI, true);
path.moveTo(95, 60);
path.arc(90, 60, 5, 0, 2*Math.PI, true);
path.moveTo(75, 70);
path.lineTo(75, 78);
ctx.strokeStyle="white"; // 設(shè)置繪制筆頭的顏色
ctx.stroke(path); // 將所設(shè)定的路徑 畫 出來
8. 繪制文本陰影
canvas利用fillText()來規(guī)定文本,我們可以設(shè)置文本的字體,顏色,陰影等,與CSS完全一致。語法
c.fillText(text, padding-left, padding-top);
效果先看

給文字繪上陰影
javascript代碼
var c = document.getElementById("cv");
var ctx = c.getContext("2d");
ctx.shadowOffsetX = 4;
ctx.shadowOffsetY = 4;
ctx.shadowBlur = 4;
ctx.shadowColor = '#FF0000';
ctx.font = '18px Arial';
ctx.fillStyle = '#333333';
ctx.fillText('帶陰影的文字', 20, 40);
9. 繪制空心文本
繪制語法
c.strokeText(text, padding-left, padding-top);
效果先看

空心文字
很簡單,在上例的基礎(chǔ)上我做了一下兩個地方的修改,就得到了以上的效果。javascript代碼
ctx.font = '24px Arial';
ctx.strokeText('果汁涼茶', 25, 70);
10. 繪制漸變色
漸變色可以填充在矩形,圓形,線條,文本等等各種形狀中,填充我們指定的顏色繪制語法
// 創(chuàng)建 線性漸變
createLinearGradient( start_x, start_y, end_x, end_y);
// 創(chuàng)建一個徑向/圓/放射性漸變
createRadialGradient(start_origin_x, start_origin_y, start_r, end_origin_x, end_origin_y, end_r)
- 當(dāng)我們使用漸變對象時,必須使用至少兩種顏色作為停止顏色。
- addColorStop()方法指定顏色停止,參數(shù)使用坐標來描述,可以是0-1;
- 使用漸變,設(shè)置fillStyle或strokeStyle()的值為漸變,然后繪制形狀,如矩形,文本,線條 。
createLinearGradient() 實例:
效果先看

線性漸變顏色填充
javascript代碼
var c = document.getElementById("cv");
var ctx = c.getContext("2d");
// 創(chuàng)建漸變規(guī)則
var grd = ctx.createLinearGradient(0, 0, 200, 0);
grd.addColorStop(0, "#ff0000");
grd.addColorStop(0.25, "#ffffff");
grd.addColorStop(0.5, "#00ff00");
grd.addColorStop(0.75, "#00ffff");
grd.addColorStop(1, "#ffff00");
// 將漸變顏色填充到畫布上
ctx.fillStyle = grd;
ctx.fillRect(10, 10, 180, 80);
createRadialGradient() 實例
效果先看

放射性漸變顏色填充
html代碼
<canvas id="cv" width="200" height="200">
您的瀏覽器不支持canvas
</canvas>
javascript代碼
var c = document.getElementById("cv");
var ctx = c.getContext("2d");
// 創(chuàng)建漸變規(guī)則
var grd = ctx.createRadialGradient(100, 100, 3, 100, 100, 100);
grd.addColorStop(0, "#ff0000");
grd.addColorStop(0.25, "#ffffff");
grd.addColorStop(0.5, "#00ff00");
grd.addColorStop(0.75, "#00ffff");
grd.addColorStop(1, "#ffff00");
// 將漸變顏色填充到畫布上
ctx.fillStyle = grd;
ctx.fillRect(10, 10, 180, 180);
11. 使用圖像
把一幅圖放置到畫布上,使用以下方法
使用語法
drawImage(image, start_x, start_y)
效果先看

圖片背景
javascript代碼
var c = document.getElementById("cv");
var ctx = c.getContext("2d");
var img=new Image()
img.src="flower.png"
cxt.drawImage(img,0,0);
結(jié)束語
除了能繪制基本的形狀和文本,還可以實現(xiàn)動畫、縮放、各種過濾和像素 轉(zhuǎn)換等高級操作。 如果考慮實現(xiàn)非常浮渣的操作,考慮一下優(yōu)化方案:
- 通過創(chuàng)建一個不可見的canvas來繪圖,然后將最終繪制的結(jié)果復(fù)制到頁面的可見的canvas中;
- 盡量使用整數(shù)坐標而不是浮點數(shù);
- 可以創(chuàng)建多個重疊的Canvas繪制不同的層,而不是在一個Canvas中繪制非常復(fù)雜的圖;
- 北京圖片如果不變,可以直接使用<img>標簽并放到最底層。
作者:果汁涼茶丶
鏈接:https://www.jianshu.com/p/7bb4896be61c
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。