- 最基本的使用
- 創(chuàng)建一個(gè)畫布
- 所有的操作都在畫布的context上面
- canvas是基于狀態(tài)而不是基于對(duì)象的,比如說(shuō)顏色都是賦值給context,并不是一條線
- canvas 標(biāo)簽
<canvas id="myCanvas" height="200" width="100"></canvas>
- 創(chuàng)建一個(gè)畫布
- 使用javascript來(lái)繪制圖像
- 基本步驟:
var c = document.getElementById("myCanvas");//前提是有這個(gè)canvas元素 var ctx = c.getContext("2d")//創(chuàng)建getContext("2d")對(duì)象 //下面就可以繪圖了。在ctx對(duì)象上
-
getContext()
,獲得渲染上下文和他的繪畫功能途茫,只有一個(gè)參數(shù)-上下文的格式 - 繪制矩形
fillRect(x,y,width,height)//繪制一個(gè)填充的矩形 strokeRect(x,y,width,height)//繪制一個(gè)矩形的邊框(也就是一個(gè)帶邊框的矩形啦) clearRect(w,y,width,height)//清除指定矩形區(qū)域,讓清楚部分完全透明
- 繪制路徑
ctx.beginPath()//必須要先新建一條路徑,如果沒(méi)有beginPath()那么,會(huì)從延續(xù)之前的路徑哆键,所謂的延續(xù)表現(xiàn)出來(lái)就是“連著”---從上次結(jié)束的地方開始,如果要想獨(dú)立畫瘦锹,那最好的習(xí)慣就是每次開始前begin籍嘹,結(jié)束后close closePath()//閉合路徑之后圖形繪制命令又重新指向到上下文中,在繪制封閉多邊形的時(shí)候闪盔,建議成對(duì)使用 stroke()//通過(guò)線條來(lái)繪制圖形輪廓 fill()//通過(guò)填充路徑的內(nèi)容區(qū)域生成實(shí)心的圖形
- 移動(dòng)筆觸
moveTo(x,y)//相當(dāng)于從哪里開始畫圖的意思
- 線
lineTo(x,y)//繪制一條從當(dāng)前位置到指定x,y的直線(這里的x,y是終點(diǎn)),指定線段的終點(diǎn)
- 曲線
-
quadraticCurveTo(cpx,cpy,x,y)
,二次貝賽爾曲線路徑的方法辱士,接受兩個(gè)點(diǎn)為參數(shù)泪掀,第一個(gè)點(diǎn)是控制點(diǎn),第二個(gè)是終點(diǎn)颂碘,起點(diǎn)在就是當(dāng)前moveTo的點(diǎn)异赫,這樣可以畫一個(gè)基于起點(diǎn)到終點(diǎn),受控于控制點(diǎn)的一個(gè)曲線凭涂,通俗一點(diǎn)的理解就是控制點(diǎn)就像一只手把一條線拽起來(lái)一樣祝辣,注意,并不是把一條直線拽起來(lái)切油,如果是拽直線蝙斜,那就成折線了,而不是曲線澎胡。并且曲線永遠(yuǎn)不會(huì)觸碰到控制點(diǎn)孕荠,而會(huì)在中途偏離控制點(diǎn)。 bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y)
arcTo(cp1x,cp1y,cp2x,cp2y,radius)
-
- 圓弧
arc(x,y,radius,startAngle,endAngle,anticlockwise)//畫一個(gè)以(x,y)為圓心攻谁,radius為半徑稚伍,從startAngle開始到endAngle結(jié)束,按照anticlockwise給定的方向(默認(rèn)為順時(shí)針)來(lái)生成戚宦,需要注意的是startAngle和endAngle的單位是弧度个曙,不是度數(shù),角度與弧度的js表達(dá)式:radians=(Math.PI/180)*degress.
色彩
fillStyle = color
設(shè)置圖形的填充顏色受楼,strokeStyle = color
設(shè)置線條的顏色透明度
globalAlpha = transparencyValue
,取值范圍0-1
ctx.globalAlpha = 0.2
- line Styles
lineWidth //設(shè)置線條寬度垦搬,默認(rèn)為1.0
lineCap //設(shè)置線條末端樣式?什么鬼艳汽,其實(shí)就是線條的帽子猴贰,值有butt/round/square,默認(rèn)值為butt
lineJoin //設(shè)置線條與線條之間相交處的樣式,值有round/bevel/miter,默認(rèn)是miter
miterLimit//當(dāng)lineJoin屬性設(shè)置為miter的時(shí)候河狐,該屬性可用于控制兩條相交線外側(cè)交點(diǎn)與內(nèi)側(cè)交點(diǎn)的距離米绕,必須是一個(gè)大于零的有限的數(shù)字,默認(rèn)值為10.
getLineDash()//返回一個(gè)包含當(dāng)前虛線樣式馋艺,長(zhǎng)度為非負(fù)偶數(shù)的數(shù)組
setLineDash()//設(shè)置當(dāng)前虛線樣式
lineDashOffset//設(shè)置虛線樣式的起始偏移量
lineCap三個(gè)屬性見(jiàn)下圖

lineJoin三個(gè)屬性見(jiàn)下圖

- 使用虛線
ctx.setLineDash([4,2])//接受一個(gè)數(shù)組作為參數(shù)栅干,來(lái)指定線段與間隙的交替
ctx.lineDashOffset = 0//設(shè)置起始偏移量
- 漸變
createLinearGradient(x1,y1,x2,y2)//指定漸變的起點(diǎn)和終點(diǎn)
createRadialGradient(x1,y1,r1,x2,y2,r2)//確定兩個(gè)圓
gradient.addColorStop(offset,color)//上色,offset取值范圍是0-1,表示漸變中開始用于結(jié)束之間的位置捐祠,color就是在offset位置顯示的顏色值
用法舉例
var lineargradient = ctx.createLinearGradient(0,0,150,150);
lineargradient.addColorStop(0,'black')碱鳞;//定義漸變的顏色
ctx.fillStyle = lineargadient;//把漸變顏色給fillstyle或者strokestyle都行
ctx.fillRect(0,0,200,200)//這樣就創(chuàng)建出一個(gè)漸變的矩形
- 圖案樣式
createPattern(image,type)//image可以是一個(gè)image對(duì)象的引用或者另外一個(gè)canvas對(duì)象,type必須是repeat/repeat-x/repeat-y/no-repeat之一
舉例:
var img = new Image()//第一次見(jiàn)
img.src = 'someImage.png';
img.onloda = function(){
var ptn = ctx.createPattern(img,'repeat');
ctx.fillStyle = ptn;
ctx.fillRect(0,0,150,150)
}
- 陰影
shadowOffsetX //設(shè)定陰影在x軸上延伸距離雏赦,默認(rèn)為0
shadowBlur //設(shè)定陰影的模糊程度劫笙,默認(rèn)為0
shadowColor //設(shè)定陰影的顏色,默認(rèn)是全透明的黑色
- 繪制文本
fillText(text,x,y [,maxWidth])//在指定的位置填充指定文本星岗,最大寬度可選
strokeText(text,x,y [,maxWidth])//在指定的位置繪制文本邊框(也就是空心的文字啦)填大,最大寬度可選
舉例:
ctx.font = "48px serif";
ctx.fillText('Hello world',10,50)
- 文本的樣式
font //設(shè)置字體大小和字體名稱
textAlign //文本對(duì)齊選項(xiàng),值start/end/left/right/center俏橘,默認(rèn)start
textBaseline //基線對(duì)齊選項(xiàng)允华。值top/hanging/middle/alphabetic,ideographic,bottom,默認(rèn)alphabetic
direction //文本方向,值ltr/rtl/inherit,默認(rèn)inherit
- 測(cè)量文本
measureText()
返回一個(gè)textMetrics對(duì)象的寬度寥掐,所在像素靴寂,體現(xiàn)文本特性的屬性
var text = ctx.measureText('foo');
text.width;//就可以輸出寬度了
-
應(yīng)用圖像
canvas圖像操作能力很強(qiáng)大
- 引入圖像
1,獲得一個(gè)指向HTMLImageElement的對(duì)象或則另一個(gè)canvas的引用作為源召耘,也可以通過(guò)提供一個(gè)url的 讓是來(lái)使用圖片 2百炬,使用drawImage()函數(shù)將圖片繪制到畫布上
- 獲得需要繪制的圖片
HTMLImageElement //由Image()構(gòu)造出來(lái),或者任何的<img>元素 HTMLVideoElement//可以用一個(gè)html的<video>元素作為圖片遠(yuǎn)污它,抓取某一幀作為一個(gè)圖像 HTMLCanvasElement//使用一個(gè)<canvas>元素作為圖片源 ImageBitmap//高性能的位圖剖踊,可以從上述的所有源一集其它幾種源中生成
- 繪制圖片
所謂繪制圖片就是在圖片上畫的意思
drawImage(image,x,y)//image是image或者canvas對(duì)象,x衫贬,y是在其目標(biāo)canvas里的起始目標(biāo)
- 縮放圖片
drawImage(image,x,y,width,height)//參數(shù)比上面多了兩個(gè)德澈,控制當(dāng)canvas畫入的時(shí)候應(yīng)該縮放的大小
- 切片
也就是裁剪圖片,有點(diǎn)意思
drawImage(image,sx,sy,sWidth,sHeight,dx,dy,dWidth,dHeight)//參數(shù)見(jiàn)下圖,前5個(gè)和上面的一樣
slicing- 控制圖像的縮放行為
cx.mozImageSmoothingEnabled = false //火狐
變形
變形操作都是在對(duì)一個(gè)圖像設(shè)置好屬性之后固惯、繪制之前用的
- 狀態(tài)的保存和恢復(fù)
save()
, 用來(lái)保存canvas狀態(tài)梆造,canvas狀態(tài)保存在一個(gè)棧中,保存一次葬毫,當(dāng)前的狀態(tài)就入棧镇辉,返回上一步的操作,就是restore()
供常,恢復(fù)狀態(tài) - 移動(dòng)(translating)
translate(offsetx,offsety)//offsetx是左右偏移量摊聋,offsety是上下偏移量,變形前保存狀態(tài)是個(gè)很好的習(xí)慣,translate移動(dòng)的是canvas和他的原點(diǎn)到一個(gè)不同的位置(也就是將canvas的原點(diǎn)進(jìn)行了偏移)
- 旋轉(zhuǎn)(rotating)
rotate(angle)//angle是以順時(shí)針為方向栈暇、以弧度為單位的值
- 縮放(scaling)
scale(x,y)//x麻裁,y是橫軸和縱軸的縮放因子,必須為正值源祈,比1小是縮小煎源,比1大是放大,默認(rèn)情況下香缺,canvas 的 1 單位就是 1 個(gè)像素手销。舉例說(shuō)万伤,如果我們?cè)O(shè)置縮放因子是 0.5拒贱,1 個(gè)單位就變成對(duì)應(yīng) 0.5 個(gè)像素跛溉,這樣繪制出來(lái)的形狀就會(huì)是原先的一半触菜。同理,設(shè)置為 2.0 時(shí)兽埃,1 個(gè)單位就對(duì)應(yīng)變成了 2 像素侥钳,繪制的結(jié)果就是圖形放大了 2 倍。
- 變形(transforms)
transform(m11,m12,m21,m22,dx,dy)//目前沒(méi)懂
移動(dòng)柄错、旋轉(zhuǎn)舷夺、縮放,是疊加的售貌,比如之前已經(jīng)translate(100,100),左右上下偏移一百给猾,此時(shí)位置為a點(diǎn),如果后面沒(méi)有移回來(lái)颂跨,又用了translat(200,200),那么是在a的基礎(chǔ)上繼續(xù)偏移敢伸,所以這個(gè)時(shí)候restore 的作用就來(lái)了,恢復(fù)狀態(tài)毫捣,恢復(fù)在save時(shí)候的狀態(tài)
- 動(dòng)畫
所謂動(dòng)畫详拙,就是不停的重繪,達(dá)到一種動(dòng)的視覺(jué)效果
-
基本步驟
- 清空canvas
- 保存canvas狀態(tài)
- 繪制動(dòng)畫圖形
- 恢復(fù)canvas狀態(tài)蔓同,然后重繪下一幀
-
window.requestAnimationFrame(callback)
用來(lái)在頁(yè)面重繪之前饶辙,通知瀏覽器調(diào)用一個(gè)指定的函數(shù),如果想要得到連貫的逐幀動(dòng)畫斑粱,函數(shù)中必須要重新調(diào)用,用法:
function callback(){ window.requestAnimationFrame(callback);// 放在第一行 //函數(shù)體 }
-
動(dòng)畫中的公式
- 三角學(xué)基礎(chǔ)函數(shù)
- sine of angle = opposite/hypotenuse
- cosine of angle = adjacent/hypotenuse
- tangent of angle = opposite/adjacent
- 角度與弧度互轉(zhuǎn)
- radians = degrees * Math.PI / 180
- degrees = radians * 180 / Math.PI
- 創(chuàng)建波
(function drawFrame(){ window.requestAnimationFrame(drawFrame); angle += speed; }())
- 創(chuàng)建圓形
(function drawFrame(){ window.requestAnimationFrame(drawFrame); xposition = centerX + Math.cos(angle)*radius; yposition = centerY + Math.sin(angle)*radius; angle += speed; }())
- 創(chuàng)建橢圓形
(function drawFrame(){ window.requestAnimationFrame(drawFrame); xposition = centerX + Math.cos(angle)*xradius; yposition = centerY + Math.sin(angle)*yradius; angle += speed; }())
- 獲取兩點(diǎn)間的距離
dx = x2 - x1; dy = y2 - y1; distance = Math.sqrt(dx*dx + dy*dy)
- 三角學(xué)基礎(chǔ)函數(shù)
-
保存文件
-
canvas.toDataURL(type,encoderOptions)
,type是圖片格式(可選)弃揽,默認(rèn)image/png,encoderOptions是圖片質(zhì)量(可選),默認(rèn)范圍為0-1则北,默認(rèn)值0.92
-
-
碰撞檢測(cè)
碰撞檢測(cè)就是判定兩個(gè)物體是否在同一時(shí)間內(nèi)占用同一塊空間
- 碰撞檢測(cè)的方法:
- 從幾何圖形的角度來(lái)檢測(cè)矿微,就是判斷一個(gè)物體是否和另一個(gè)物體有重疊
- 也可以檢測(cè)距離,就是判斷兩個(gè)物體是否足夠近到發(fā)生碰撞尚揣。
- 基于幾何圖形的碰撞檢測(cè)
- 兩個(gè)物體間的碰撞檢測(cè)
- 邊界框算法:(就是把圖形放到一個(gè)矩形里面涌矢,這個(gè)矩形由位置和大小計(jì)算得來(lái))
utils.intersectx = function (rectA, rectB) { return !(rectA.x + rectA.width < rectB.x || rectB.x + rectB.width < rectA.x || rectA.y + rectA.height < rectB.y || rectB.y + rectB.height < rectA.y)}
- 兩個(gè)物體間的碰撞檢測(cè)
- 基于距離的的碰撞檢測(cè)
先確定兩個(gè)物體的最小距離,再計(jì)算當(dāng)前距離快骗,然后進(jìn)行比較
- 碰撞檢測(cè)的方法:
-
小結(jié)
- canvas畫布常用接口
- canvas.width
- canvas.height
- canvas.getContext('2d')
- 所謂狀態(tài)娜庇,就是顏色、邊框方篮、線條寬度等等這些具體的屬性
- 矩形的繪制
- rect(x, y, width, height),繪制一個(gè)矩形名秀,僅僅是路徑,沒(méi)有任何狀態(tài)(也就是沒(méi)有顏色沒(méi)有邊框)
- fillRect(x, y, width, height)藕溅,繪制一個(gè)有填充色的矩形
- strokeRect(x, y, width, height)匕得,繪制一個(gè)有邊框的矩形
- canvas畫布常用接口
-
TIPS
- 一個(gè)有填充色并且描邊的圖像,應(yīng)該先填充后描邊(先f(wàn)ill后stroke)巾表,如果反過(guò)來(lái)的話汁掠,邊的一半會(huì)被填充色覆蓋掉
- 所謂速度略吨、加速度的問(wèn)題:
物理上v = at,x=v*t; 在canvas上沒(méi)有時(shí)間的概念考阱,因?yàn)槭侵饚秩镜慕希梢韵胂蟪梢粠褪?s,但是時(shí)間有遞加的概念羔砾,而幀并沒(méi)有,所以對(duì)應(yīng)過(guò)來(lái)如果想要取得有“加速度的效果”偶妖,那么x += a,也就是疊加一個(gè)加速度的值姜凄,這樣就像有了加速度一樣;如果對(duì)應(yīng)過(guò)來(lái)想要取得有“速度”的效果趾访,那么就是x += v,也就是位置疊加一個(gè)速度,這樣就像有了速度一樣
- 角度問(wèn)題:canvas中逆時(shí)針角度為正,順時(shí)針角度為負(fù)