簡單介紹canvas
<canvas>
與<img>
標籤很像,但是沒有src和alt屬性,只有width和height屬性。
css定義的尺寸與canvas的尺寸比例不一致時,會出現扭曲。
canvas起初是空白的,要找到渲染上下文來繪製。 getContext() 該方法用來獲取渲染上下文和繪製功能。
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');// 需要檢查支援性,是否支援canvas.getContext
複製程式碼
矩形
fillRect(x, y, width, height);// 填充矩形
strokeRect(x, y, width, height);//矩形邊框
clearRect(x, y, width,height);// 清除指定矩形區域,清除部分為透明的
複製程式碼
繪製路徑:
- 建立路徑的起始點
- 使用畫圖命令,畫出路徑
- 路徑封閉
- 路徑生成,繪製圖形(描邊,填充)
beginPath()
新建一條路徑,生成之後,圖形繪製命令被指向到路徑上生成路徑。
列表清空重置,重新繪製新的圖形。
closePath()
閉合路徑之後圖形繪製命令又重新指向到上下文中。
非必需,當你呼叫fill()函式時,所有沒有閉合的形狀都會自動閉合,所以你不需要呼叫closePath()函式。但是呼叫stroke()時不會自動閉合。
stroke()
通過線條來繪製圖形。如果用線條繪製必須用closePath()來閉合曲線。
fill()
通過填充路徑的內容區域生成實心的圖形。
moveTo(x, y)
將筆觸移動到x,y座標點處。
lineTo(x, y)
繪製直線。
arc(x, y, radius, startAngle, endAngle, anticlockwise)
圓心座標,半徑,起始角度,結束角度,false順時針,true逆時針。
三點鐘方向為0°(弧度),弧度=(Math.PI/180)*角度。
arcTo(x1, y1, x2, y2, radius)
根據給定的控制點和半徑畫一段圓弧,再以直線連線兩個控制點。
rect(x, y, width, height)
繪製一個左上角座標為(x,y),寬高為width以及height的矩形。筆觸自動置回(0,0)。
quadraticCurveTo(cp1x, cp1y, x,y)
繪製二次貝塞爾曲線,cp1x,cp1y為一個控制點,x,y為結束點。
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
繪製三次貝塞爾曲線,cp1x,cp1y為控制點一,cp2x,cp2y為控制點二,x,y為結束點。藍色是起始點和結束點,紅色是控制點。
path2D物件:用來快取和記錄繪畫命令,可快速回顧繪製路徑。
Path2D()
會返回一個新初始化的Path2D物件(可能將某一個路徑作為變量——建立一個它的副本,或者將一個包含SVG path資料的字元串作為變量)。
new Path2D(); // 空的Path物件
new Path2D(path); // 克隆Path物件
new Path2D(d); // 從SVG建立Path物件
Path2D.addPath(path [, transform]);// 新增了一條路徑到當前路徑(可能新增了一個變換矩陣)。
複製程式碼
新的Path2D API有另一個強大的特點,就是使用SVG path data來初始化canvas上的路徑。這將使你獲取路徑時可以以SVG或canvas的方式來重用它們。
var p = new Path2D("M10 10 h 1 80 v 80 h -80 Z");// 將先移動到點 (M10 10) 然後再水平移動80個單位(h 80),然後下移80個單位 (v80),接著左移80個單位 (h -80),再回到起點處 ( z)。
複製程式碼
透明度:TransparencyValue
globalAlpha = transparencyValue;// 有效值(0.0~1.0),完全透明~完全不透明
複製程式碼
線性樣式
lineWidth = value
設定線條寬度。屬性值必須為正數。預設值是1.0。
lineCap = type
設定線條末端樣式。type
的值有butt
,round
和 square
。預設是 butt
。
lineJoin = type
設定線條與線條間接合處的樣式。round
, bevel
和miter
。預設是 miter
。
miterLimit = value
限制當兩條線相交時交接處最大長度。
所謂交接處長度(斜接長度)是指線條交接處內角頂點到外角頂點的長度。
getLineDash()
返回一個包含當前虛線樣式,長度為非負偶數的陣列。
setLineDash(segments)
設定當前虛線樣式。
lineDashOffset = value
設定虛線樣式的起始偏移量。
用 setLineDash
方法和 lineDashOffset
屬性來制定虛線樣式。
setLineDash
方法接受一個陣列,來指定線段與間隙的交替;
lineDashOffset
屬性設定起始偏移量。
漸變:以用線性或者徑向的漸變來填充或描邊
新建一個 canvasGradient 物件,並且賦給圖形的 fillStyle 或 strokeStyle 屬性。
createLinearGradient(x1, y1, x2, y2)
createLinearGradient
方法接受 4 個引數,表示漸變的起點 (x1,y1)
與終點 (x2,y2)
。
createRadialGradient(x1, y1, r1, x2, y2, r2)
createRadialGradient
方法接受 6 個引數,前三個定義一個以 (x1,y1)
為原點,半徑為 r1 的圓,後三個引數則定義另一個以(x2,y2)
為原點,半徑為 r2 的圓。
gradient.addColorStop(position, color)
addColorStop
方法接受 2 個引數,position 引數必須是一個 0.0 與 1.0 之間的數值,表示漸變中顏色所在的相對位置。
圖案樣式patterns
createPattern(image, type)
該方法接受兩個引數。Image
可以是一個 Image
物件的引用,或者另一個 canvas
物件。
Type
必須是下面的字元串值之一:repeat
,repeat-x
,repeat-y
和 no-repeat
。
陰影shadow
shadowOffsetX = float;
shadowOffsetY = float;
複製程式碼
shadowOffsetX
和 shadowOffsetY
用來設定陰影在X和Y軸的延伸距離,它們是不受變換矩陣所影響的。負值表示陰影會往上或左延伸,正值則表示會往下或右延伸,它們預設都為 0。
shadowBlur = float
複製程式碼
shadowBlur
用於設定陰影的模糊程度,其數值並不跟畫素數量掛鉤,也不受變換矩陣的影響,預設為 0。
shadowColor = color
複製程式碼
shadowColor
是標準的 CSS 顏色值,用於設定陰影顏色效果,預設是全透明的黑色。
canvas填充規則:
nonzero
:non-zero winding rule, 預設值. 填充evenodd
: even-odd winding rule,鏤空
動畫:
- 清空canvas:clearRect();
- 儲存canvas狀態
- 繪製動畫圖形:重繪動畫幀
- 恢復canvas狀態:如果已經儲存了 canvas的狀態,可以先恢復它,然後重繪下一幀。
你可以使用setInterval()
方法,它就可以定期執行指定程式碼。如果我們需要做一個遊戲,我們可以使用鍵盤或者滑鼠事件配合上setTimeout()
方法來實現。通過設定事件監聽,我們可以捕捉使用者的互動,並執行相應的動作。
採用window.requestAnimationFrame()
實現動畫效果。這個方法提供了更加平緩並更加有效率的方式來執行動畫,當系統準備好了重繪條件的時候,才呼叫繪製動畫幀。一般每秒鐘回撥函式執行60次,也有可能會被降低。
變形transformations:
save()
和 restore()
: save 和 restore 方法是用來儲存和恢復 canvas 狀態的,canvas的狀態儲存在棧中。
tanslate(x, y)
; 左右,上下平移。
rotate
旋轉。
scale
縮放。
transform(m11, m12, m21, m22, dx, dy)
這個方法是將當前的變形矩陣乘上一個基於自身引數的矩陣,在這里我們用下面的矩陣
m11 m21 dx
m12 m22 dy
0 0 1
複製程式碼
m11:水平方向的縮放
m12:水平方向的傾斜偏移
m21:豎直方向的傾斜偏移
m22:豎直方向的縮放
dx:水平方向的移動
dy:豎直方向的移動
複製程式碼
setTransform(m11, m12, m21, m22, dx, dy)
resetTransform()
複製程式碼
canvas優化
使用requestAnimationFrame
進行動畫迴圈
setTimeout
和 setInterva
l並非是專為連續迴圈產生的 API,所以可能無法達到流暢的動畫表現,故用 requestAnimationFrame
,可能需要polyfill
const raf = window.requestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.mozRequestAnimationFrame
|| window.oRequestAnimationFrame
|| window.msRequestAnimationFrame
|| function(callback) {
window.setTimeout(callback, 1000 / 60)
}
複製程式碼
利用剪輯區域來處理動畫背景或其他不變的影象
背景比較複雜可以使用剪輯區域技術,通過每幀較少的繪製來獲得較好的效能。
利用剪輯區域技術來恢復上一幀動畫所佔背景圖的執行步驟:
- 呼叫 context.save(),儲存螢幕 canvas的狀態
- 通過呼叫 beginPath來開始一段新的路徑
- 在 context物件上呼叫 arc()、rect()等方法來設定路徑
- 呼叫 context.clip()方法,將當前路徑設定為螢幕 canvas的剪輯區域
- 擦除螢幕 canvas中的影象(實際上只會擦除剪輯區域所在的這一塊範圍)
- 將背景影象繪製到螢幕canvas上(繪製操作實際上只會影響剪輯區域所在的範圍,所以每幀繪製影象畫素數更少)
- 恢復螢幕 canvas的狀態引數,重置剪輯區域
離屏緩衝區(離屏canvas)
先繪製到一個離屏 canvas
中,然後再通過 drawImage
把離屏 canvas
畫到主 canvas
中,就是把離屏 canvas
當成一個快取區。把需要重複繪製的畫面資料進行快取起來,減少呼叫 canvas
的 API的消耗。
const cacheCanvas = document.createElement('canvas')
const cacheCtx = cacheCanvas.getContext('2d')
cacheCtx.width = 200
cacheCtx.height = 200
// 繪製到主canvas上
ctx.drawImage(0, 0)
複製程式碼
必要時,可以使用多個離屏 canvas
另外,離屏canvas
不再使用時,最好把手動將引用重置為 null
,避免因為 js和dom之間存在的關聯,導致垃圾回收機制無法正常工作,佔用資源。
儘量利用CSS
儘量少的呼叫 canvas API
相比於正常的js操作,頻繁的呼叫canvasAPI更加消耗資源。
避免阻塞
在進行某些耗時操作,例如計算大量資料,一幀中包含了太多的繪製狀態,大規模的 DOM操作等,可能會導致頁面卡頓,影響使用者體驗,可以通過以下兩種手段:
-
web worker
web worker
最常用的場景就是大量的頻繁計算,減輕主執行緒壓力,如果遇到大規模的計算,可以通過此 API分擔主執行緒壓力,此 API相容性已經很不錯了,既然canvas
可以用,那web worker
也就完全可以考慮使用。 -
分解任務
滿足:
1.迴圈處理操作並不要求同步
2.資料並不要求按照順序處理根據任務總量分配: 根據執行時間分配: 複製程式碼
以上內容均是看文件學習歸納的常用的基礎的知識點,覺得有用的小夥伴點個小心心吧