讓自己也能使用Canvas
<canvas> 是 HTML5 新增的元素,可使用JavaScript指令碼來繪製圖形。例如:畫圖,合成照片,建立動畫甚至實時視訊處理與渲染。
相容性方面,除了一些骨灰級瀏覽器IE6、IE7、IE8等,大部分現代瀏覽器都能支援。
一、屬性與方法
1)屬性
<canvas> 看起來和 <img> 元素很相像,唯一的不同就是它並沒有 src 和 alt 屬性。實際上,<canvas> 標籤只有兩個屬性—— width和。
<canvas id="strick" width="150" height="150"></canvas>
還有些預設的屬性,id、style等
2)方法
1. getContext(in DOMString contextId)
canvas起初是空白的。為了展示,首先指令碼需要找到渲染上下文,然後在它的上面繪製。這個方法是用來獲得渲染上下文和它的繪畫功能。
contextType中可選的引數有“2d”、“webgl”、“webgl2”、“bitmaprenderer”。
contextAttributes屬性會根據 “2d” 或 “webgl” 會需要不同的引數。
var canvas = document.getElementById('strick'); var ctx = canvas.getContext('2d');
2. (in optional DOMString type, in any ...args)
返回一個data: URL,將canvas中的圖片編碼成字串形式,有多種格式選擇,type引數的預設值為image/png。
曾做過一個圖片合成的功能,就使用到了這個功能。這裡要注意一個“畫布汙染”。
就是嵌入的圖片是跨域的,那麼就不能使用這個方法。在《》做過簡單的分析。
3. (in Function callback, in optional DOMString type, in any ...args)
返回一個Blob(binary large object)物件。Blob代表了一段二進位制資料,就是一個包含只讀原始資料的類檔案物件。
二、繪製2D圖形
在MDN上面有個基礎教程《》,覆蓋面蠻全的。
1)座標空間
畫布的起點為左上角,這個起始點通過方法 可以自定義,例如做旋轉縮放等操作。
上圖所示,canvas的座標軸與普通的座標軸是相反的。
所以順時針是正值,逆時針是負值。
2)繪製形狀
矩形是canvas支援的唯一一種原生的圖形繪製。要畫其他形狀,就需要通過繪製路徑實現。繪製矩形提供了3個方法。
路徑是通過不同顏色和寬度的線段或曲線相連形成的不同形狀的點的集合。有操縱路徑和。
操作過程大致為4步,先建立路徑起始點,再畫出路徑,然後閉合路徑,最後填充。
1. 簡單圖形
下圖中是些簡單的圖形,兩個三角形中有一個是旋轉了畫布的,逆時針畫的半圓,三個圓圈與一個半圓組成的笑臉,用貝塞爾曲線畫的對話氣泡,可以。
2. 複雜圖形
在CSS中,邊框、字型等都能設定寬度、大小、顏色等,高階點的還有陰影、漸變、rgba等。
在canvas中也有相應的操作,繪製文字、線型、文字樣式、、漸變和圖案、陰影。
有網友畫了頭灰太狼,非常逼真,可以線上除錯,通過檢視原始碼,裡面用到的就是beginPath、moveTo、quadraticCurveTo等路徑相關的方法或屬性。
3)使用圖片
canvas可以對圖片進行合成、縮放、裁剪、旋轉、變形等操作。
a. 簡單的合成
現在有些網站會讓你DIY做張海報,然後分享到朋友圈。前段時間做了個簡易的海報,僅僅是將圖片合成在一起,沒有做塗鴉等操作,詳細的介紹可以檢視《》
b. 高階點的合成
高階點的製作海報,能夠輸入自定義的文字,用到了上面所說的繪製形狀的一些概念,在看原始碼的時候,發現引用了指令碼“”,解決canvas 在高清屏下繪製圖片變模糊。
簡單合成 | 高階合成 |
除了基礎的操作,還有高階的畫素操作,獲取圖片中某一畫素的RGBA,然後修改其中的R、G、B或A的值,來修改顏色或透明度。
例如滑鼠移動獲取RGBA值,將彩色照變成黑白照,打馬賽克等。
第一張圖片是獲取畫素值,第二張圖是變灰。
除了能操縱圖片,canvas還能操縱視訊,也就是<video>標籤。
4)變換矩陣
CSS3中的transform有個矩陣的概念,旋轉、平移、扭曲、縮放等都可以用矩陣來實現。關於CSS3的動畫可以參考《》
canvas中有一個()方法,實現旋轉,但其實旋轉的是canvas畫布,並不是旋轉畫出來的那個圖形。
如果用()方法的話,就可以實現旋轉圖形。這邊有個對比例項,可以線上除錯。
2D渲染的上下文矩陣如下,可以忽略最後一行:
2D渲染的座標計算如下,關於計算過程可以研究下線性代數,簡單點說就是a和x、y、1分別相乘。
rotate與skew的矩陣計算會涉及到三角函式中的正弦、餘弦還有正切。
//scale()對應的矩陣 下面是CSS3中的寫法,對應的方法是CanvasRenderingContext2D.transform matrix(sx,0,0,sy,0,0);/*sx和sy分別對應X軸和Y軸的縮放比率*/ //rotate()對應的矩陣 //在JS中θ對應的是弧度轉換公式為 弧度= 2 * PI / 360 * 角度 matrix(cosθ,sinθ,-sinθ,cosθ,0,0); //skew()對應的矩陣 //θy對應的是Y軸的弧度 θx對應的是X軸的弧度 matrix(1,tan(θy),tan(θx),1,0,0)
矩陣計算還會涉及到很多其他的數學知識,例如一次函式,我基本都已經忘記了,囧,都得重新查看了。
有個線上編輯matrix的網站,
5)相關的計算公式
a. 三角函式基礎公式
JavaScript中有兩個反正切函式,(ratio)與(y, x)。
第一個方法返回一個 -pi/2 到 pi/2 弧度之間的數值,第二個方法返回一個 -pi 到 pi 之間的數值。
b. 角度與弧度的互轉
在JavaScript中,三角函式等用的是弧度,例如Math.sin、Math.cos等方法;旋轉是用角度。所以兩者之間是需要換算的。
radians是弧度,degrees是角度
c. 兩點間的距離
使用了直角三角形的勾股定理。座標軸中的P1與P2,就相當於公式中的A與B。
三、canvas動畫
要實現動畫就需要用JavaScript實現很多物理概念。
1)速度向量
速度(speed)是速度向量(velocity)中的一部分,速度向量還包括方向。
用vx表示x軸上的速度向量,有vy表示y軸上的速度向量。還可以表示角度旋轉,用vr表示。
vx為正數表示向右,負數表示向左。vy為正數表示向下,負數表示向上。
下圖就是一個向右移動的球,vx=1,詳細程式碼可以參考這裡。
2)角速度
假設物體以1個畫素的速度向45°方向移動,那麼vx和vy可以通過餘弦與正弦獲取。
速度和方向對映成一個直角三角形。
vx = Math.cos(angle)*speed;
vy = Math.sin(angle)*speed;
上圖就是經過計算後的角速度示例。
3)加速度
速度向量改變的是物體的物理位置,加速度改變的是速度向量。
下面的圖片與速度向量中的gif內容是相同的,只是每次迴圈給vx加了0.1個值。
4)邊界
處理邊界,有多種選擇,移除、置回邊界內、螢幕環繞、反彈回邊界內等。
左圖是置回邊界內,右圖是反彈回邊界內的效果。
5)摩擦力
一個比較簡單的實現是,設定一個friction(摩擦力變數,一個小於1的數字),將這個數與vx和vy分別相乘,獲取新的值。
這兩個值會越來越小,最終停止。
除了上面幾種基礎的動畫,還有些高階的動畫,緩動、彈動、碰撞檢測等。
四、canvas的優缺點
1)優點:
1. 在呈現影象、文字和動畫的時候,由於 canvas 不存在與解析 HTML 和維護分層文件模型有關的開銷,因此,在 canvas 中這些任務總是要比在 HTML 中快。
2. 可以實現一致的、跨平臺的呈現。例如瀏覽器的transform屬性,不同瀏覽器可能就需要使用自己獨特的字首。
3. 畫出來的圖形可以直接儲存為 .png 或者 .jpg的圖形。
4. 最適合於畫光柵影象(如遊戲和不規則幾何圖形等),編輯圖片還有其他基於畫素的圖形操作。
2)缺點:
1. 由於 canvas 裡面沒有dom節點,當某個元素需要執行互動事件(如click)的時候只能是通過座標來判斷。
2. 沒有實現動畫的API,你必須依靠定時器和其他事件來更新 canvas。
3. 對文字的渲染支援是比較差,例如自動換行。canvas中也不存在超連結的概念。
4. 由於在 canvas 上以程式設計方式顯示的文字其實就是點陣圖,因此搜尋爬行器將完全忽略文字。文字內容也無法被螢幕閱讀器識別。