上節(jié)文章中趁耗,給大家分享了canvas
最基礎(chǔ)的用法,包括繪制線條做瞪、控制渲染方式对粪、繪制圖形、作用域装蓬、添加陰影著拭、清理、剪切等功能牍帚,本節(jié)將繼續(xù)為大家分享canvas
的基礎(chǔ)用法儡遮,同時也是最后一節(jié)基礎(chǔ)知識分享,之后的內(nèi)容暗赶,我們將會進(jìn)入到對webgl
的分享中鄙币。
1. 文本繪制
首先我們要提到的是繪制文本,在canvas
的開發(fā)過程中蹂随,文本的內(nèi)容是肯定會存在的十嘿。本小節(jié)就來給大家分享下如何渲染文本。
1.1 繪制空心和實心文本
canvas
中提供了兩種繪制文本的方法岳锁,分別是繪制實心文本和空心文本绩衷,它們的方法分別是:
- strokeText(text, x, y, maxWidth): 繪制空心文本
- fillText(text, x, y, maxWidth): 繪制實心文本
參數(shù)介紹:
- text: 要繪制的文本內(nèi)容
-
x, y
: 坐標(biāo)點,文本左上角的坐標(biāo)點 - maxWidth: 允許渲染的最大像素寬度
栗子:
// 繪制實心文本
c.fillText('hello world', 100, 100); // 將 hello world 這個內(nèi)容從 100 100 這個點開始渲染。
// 繪制空心文本
c.strokeText('hello world', 200, 200);
如果這里你的字體是默認(rèn)大小咳燕,可能會看不到空心效果勿决。改變字體大小在下文中有分享到。
1.2 改變文本樣式
如果我們想修改字體的顏色招盲,可以根據(jù) 繪制圖形 一節(jié)中的方法低缩,使用 strokeStyle、fillStyle
來修改曹货。
1. 要設(shè)置實心文本字體為藍(lán)色
c.fillStyle = 'blue';
c.fillText('hello world', 100, 100);
2. 要設(shè)置空心字體為紅色
c.strokeStyle = 'yellow';
c.strokeText('hello world', 200, 200);
1.3 改變文本大小和字體樣式
修改字體大小和字體樣式需要用到 font = '字體大小 字體樣式’
屬性咆繁。
如:把字體改為 宋體 40px。
c.font = '40px 宋體';
如果是特殊的字體控乾,會出現(xiàn)不支持的現(xiàn)象么介。
1.4 修改文本對齊方式
文本對齊方式分為 垂直 和 水平 對齊方式。
1. 垂直方向?qū)R蜕衡。
這里需要用到 textBaseLine
這個屬性。意為按照基線對齊设拟。它有6個值慨仿,分別是:
- alphabetic: 默認(rèn)值,意為普通的字母基線纳胧×海可理解為四線三格的第三條線。
- top:文字頭部對齊基線
- hanging:懸掛基線跑慕,與top稍有不同
- middle:文字中部對齊
- ideographic:表意基線万皿。稍難理解,可看示意圖
- bottom:文字底部對齊基線
示例:
// 首先我們畫一條基準(zhǔn)線核行,讓文字按照這條線對齊
c.strokeStyle = 'blue';
c.moveTo(5, 100);
c.lineTo(700, 100);
c.stroke();
c.font = '20px 宋體';
// 枚舉可用的對齊方式牢硅。
c.textBaseline = 'top';
c.fillText('Top', 5, 100);
c.textBaseline = 'bottom';
c.fillText('Bottom', 100, 100);
c.textBaseline = 'middle';
c.fillText('Middle', 200, 100);
c.textBaseline = 'alphabetic';
c.fillText('Alphabetic', 300, 100);
c.textBaseline = 'hanging';
c.fillText('Hanging', 400, 100);
c.textBaseline = 'ideographic';
c.fillText('ideographic', 500, 100);
示例圖:
2. 水平居中
水平居中需要使用 textAlign
屬性。同樣也是基于基準(zhǔn)線對齊芝雪,有5個屬性值减余。
- start: 默認(rèn)。文本在指定的位置開始惩系。
- end: 在指定的位置結(jié)束
- center: 文本中心被放在指定位置
- left: 文本左對齊
- right: 文本右對齊
栗子:
// 創(chuàng)建基準(zhǔn)線
c.strokeStyle = 'blue';
c.moveTo(150, 20);
c.lineTo(150, 400);
c.stroke();
c.font = '30px 宋體';
// 枚舉可用的對齊方式位岔。
c.textAlign = 'start';
c.fillText('start', 150, 50);
c.textAlign = 'end';
c.fillText('end', 150, 100);
c.textAlign = 'left';
c.fillText('left', 150, 150);
c.textAlign = 'center';
c.fillText('center', 150, 200);
c.textAlign = 'right';
c.fillText('right', 150, 250);
示例圖:
3. 不固定寬高的畫布水平居中
對于寬度不固定的畫布,我們使用 textAlign
的作用就不太大了堡牡。因為此時我們需要根據(jù)畫布的寬度進(jìn)行實時計算抒抬。此時我們需要獲得兩個數(shù)值。畫布寬度和字體寬度晤柄。畫布寬度比較簡單擦剑,使用 ctx.width
就可以獲取。
字體的寬度。需要用到 measureText(text)
方法抓于。此方法可根據(jù)你設(shè)置的字體大小來返回傳入文本的像素寬度做粤。
栗子:
c.font = '20px 宋體'
const textData = c.measureText('hello world');
console.log(textData.width) // 84
設(shè)置字體寬度為 20px
,則渲染后的 hello world
占據(jù)的像素寬度為 84px
(不同瀏覽器之間會有差異)
這樣我們就可以得到水平居中的計算方式
文本x坐標(biāo) = (畫布寬 - 文本寬)/ 2
const x = (ctx.width - c.measureText('hello world')) / 2;
2. 動畫
2.1 狀態(tài)保存與恢復(fù)
分享動畫之前 捉撮,我們先來介紹 save 和 restore
這兩個方法怕品。因為我們在處理動畫的過程中,避免不了對畫布進(jìn)行旋轉(zhuǎn)巾遭、平移和縮放的操作肉康。從而導(dǎo)致之前或之后的繪制出現(xiàn)錯亂。而``save 和 restore` 這兩個方法就可以避免這個問題灼舍。
save
: 保存當(dāng)前canvas
的狀態(tài)吼和。restore
: 恢復(fù)之前保存的狀態(tài)。
2.2 變換
說到動畫骑素,無非就是對圖形的旋轉(zhuǎn)炫乓、縮放、平移這幾項內(nèi)容献丑。canvas
中提供了一系列的方法末捣。
- translate(x, y): 平移〈撮希可改變當(dāng)前畫布的原點位置箩做。
- rotate(deg) :旋轉(zhuǎn)。其中 deg 代表的是弧度制妥畏。(角度轉(zhuǎn)弧度請看初始canvas(一)的內(nèi)容)
-
scale(x,y): 縮放邦邦,
x
代表x軸縮放。y
代表y軸縮放醉蚁。
栗子:
// 原始矩形
c.save()
c.fillRect(10, 10, 100, 100);
c.restore()
// 平移50px
c.save()
c.translate(50, 50);
c.fillRect(10,10,100,100);
c.restore()
// 旋轉(zhuǎn)45度
c.save()
c.rotate(45 * Math.PI / 180);
c.fillRect(210, 110, 100, 100)
c.restore()
// x軸縮放0.5 y軸縮放1.1
c.save()
c.scale(0.5, 1.1)
c.fillRect(410, 210, 100, 100)
c.restore()
注意:translate
平移之后是可以改變畫布原點的位置的燃辖,此時如果我們需要讓某個圖形圍繞自身旋轉(zhuǎn),則需要將圖像的中心點位于畫布圓點上馍管。如下方代碼所示:
// 將畫布中心移入到 50郭赐,50 這個點
c.translate(50, 50);
setInterval(() => {
// 每次繪制之前先清空畫布,這里的原點已經(jīng)在50确沸,50這個位置了捌锭。所以需要從 -50這里開始清理。
c.clearRect(-50, -50, ctx.width, ctx.height);
// 每次旋轉(zhuǎn) 1 度
c.rotate(Math.PI / 180);
// 繪制實心矩形罗捎。
c.fillRect(-25,-25, 50,50);
}, 16)
這里就可以得到一個圍繞自身旋轉(zhuǎn)的實心矩形观谦。
2.3 transform 矩陣操作
方法接收 6
個參數(shù)。transform(a,b,c,d,e,f)
其中桨菜,
平移:涉及到
e, f
兩個參數(shù)縮放:涉及到
a, d
兩個參數(shù)拉伸:涉及到
b, c
兩個參數(shù)旋轉(zhuǎn):涉及到
a, b, c, d
四個參數(shù)
此方法在后續(xù)的講解中還會出現(xiàn)豁状,并且方法不太好理解捉偏,這里只簡單說明。不做過多介紹泻红。
3. 漸變
本小節(jié)來說下如何給圖形添加漸變色夭禽。漸變色也是我們經(jīng)常可以用到的功能谊路。添加漸變色我們需要用到下面這兩個方法
- createLinearGradient(sx,sy,ex,ey) 經(jīng)向漸變
- createRadialGradient (sx,sy,sr,ex,ey,er) 環(huán)形漸變
sx, sy, sr
代表的是起始點漸變圓的原點坐標(biāo)和半徑讹躯,ex, ey, er
代表的是終止點漸變圓的原點坐標(biāo)和半徑。漸變方法返回一個對象缠劝。我們可以使用這個返回對象的 addColorStop(position, color)
方法 執(zhí)行添加顏色的操作潮梯。
position
表示漸變的百分比,也就是漸變的位置惨恭。值是0-1
之間的浮點數(shù)秉馏。
color
是要添加的顏色
下面,我們通過一個栗子來看下如何創(chuàng)建漸變圖形脱羡。
栗子1 -- 徑向漸變:
// 創(chuàng)建徑向漸變萝究,得到漸變對象。
const lg = c.createLinearGradient(10, 10, 200, 200);
// 通過漸變對象來添加顏色
lg.addColorStop(0,"black");
lg.addColorStop(1, 'orange');
// 將得到的漸變色添加到填充樣式中轻黑。
c.fillStyle = lg;
c.fillRect(100, 100, 200, 200);
栗子2 -- 環(huán)形漸變:
// 起始點和終止點圓心坐標(biāo)相同糊肤,代表從同一點開始散發(fā)
const lg = c.createRadialGradient(150, 100, 5, 150, 100, 100);
lg.addColorStop(0,"black");
lg.addColorStop(1, 'orange');
c.fillStyle = lg;
c.arc(150, 100, 100, 0, 2 * Math.PI);
c.fill();
漸變示意圖:
4. 源目標(biāo)和透明度
4.1 透明度設(shè)置
對于透明度設(shè)置我們只需要知道一個屬性就可以。
-
globalAlpha = value:
value
的取值范圍在0-1
之間氓鄙。代表當(dāng)前畫布的透明度是多少。
4.2 源目標(biāo)設(shè)置
源與目標(biāo)設(shè)置我們需要用到 globalCompositeOperation
這個屬性业舍,它有N
個屬性值抖拦。這里我們就不一一介紹了,這里我們先繪制一個紅色的矩形舷暮,再繪制一個藍(lán)色的矩形态罪,然后我們來看下設(shè)置不同的globalCompositeOperation
會出現(xiàn)什么情況。
圖解:
有需要的話可根據(jù)上圖進(jìn)行篩查下面,看下自己需要哪種效果复颈。對應(yīng)設(shè)置。
5. 圖片繪制和背景設(shè)置
5.1 圖片繪制
對于圖片的操作在日常的工作中肯定會經(jīng)常用到沥割。canvas
中也提供了對于圖片操作的方法供開發(fā)人員使用耗啦。
注意:
在加載圖片的時候,一定要確保的是要在圖片加載完成之后再添加到畫布中机杜。因此可以給圖片使用onload事件帜讲。
如:
const image = new Image();
image.onload = function () {
// 繪制圖片操作
}
image.src = '圖片鏈接';
接下來繪制圖片的方法默認(rèn)都是存在于 onload
事件中的。
-
drawImage
可接收3,5,9
個參數(shù);- 三個參數(shù)
(img,x,y)
-
img
是圖片對象椒拗,x,y
是圖片在畫布中的原點位置
-
- 五個參數(shù)
(img,x,y似将,imageWidth,imageHeight)
;- 前三個參數(shù)不變获黔,
imageWidth,imageHeight
設(shè)置的是圖片的寬和高
- 前三個參數(shù)不變获黔,
- 九個參數(shù)
(img,x,y,imageWidth,imageHeight在验,imgx,imgy,imgw,imgh)
;- 前五個參數(shù)不改變玷氏,
imgx,imgy
表示從圖片的這個點開始取像素。imgw,imgh
表示的是取多寬多高的像素腋舌。
- 前五個參數(shù)不改變玷氏,
- 三個參數(shù)
5.2 背景設(shè)置
通過createPattern(image, repetition)
可以為畫布設(shè)置背景圖像盏触。
其中, image
代表的是圖片對象侦厚。repetition
代表的是是否平鋪耻陕,repeat:平鋪, no-repeat:不平鋪
6. 像素操作
canvas
最引入注目的功能就是對于像素點的操作刨沦。這個功能可以讓我們實現(xiàn)眾多絢麗的特效诗宣。希望小伙伴們在領(lǐng)悟了像素操作的真諦之后,也能做出絢麗的特效想诅。這個我們也成為粒子效果;
對于像素操作召庞,canvas
中提供了三個方法。
-
getImageData(x,y,w,h)
: 獲取畫布中指定位置的像素集合 前兩個參數(shù)是你想要獲取的原點位置来破,后兩個參數(shù)是你想要獲取的范圍 -
putImageData(data, x,y)
: 設(shè)置畫布中指定位置的像素集合篮灼,前兩個參數(shù)是你想要設(shè)置的原點位置 -
createImageData(data)
: 直接生成新的像素矩陣,不用獲取
栗子:
const data = c.getImageData(0, 0, 10, 10);
console.log(data);
/*
[
[1,2,3,4,5,6,7,8,9,10……],
…………
]
*/
這里我們通過 getImageData
可以獲取到一個二維數(shù)組徘禁,代表獲取到的點位圖诅诱。
數(shù)組中,每四個元素是一組送朱。分別代表 r,g,b,a
中的每一項娘荡。每個r,g驶沼,b
元素的取值范圍為 0-255
炮沐,a
的取值范圍為0-1
;
如果我們想對像素做操作,那就修改這些值回怜,如圖片取反大年、復(fù)古風(fēng)、底片…………等等玉雾,都可以實現(xiàn)翔试。
有興趣的小伙伴可以探討一下喲~
7. 曲線
-
arcTo(startx, starty, endx, endy, r)
- 此方法可以讓我們創(chuàng)建弧形線條。
startx, starty
表示弧的起始點抹凳。endx, endy
表示弧的終點遏餐。r
表示你弧的半徑。
- 此方法可以讓我們創(chuàng)建弧形線條。
示例:
c.beginPath()
c.moveTo(20,20);
c.lineTo(100,20);
c.arcTo(150,20,150,70,10); // 創(chuàng)建弧
c.lineTo(150,120);
c.stroke()
-
quadraticCurveTo(cox, coy, endx, endy)
二次貝塞爾曲線- 貝塞爾曲線可以幫我們獲得更加多變的曲線內(nèi)容赢底。
cox, coy
表示控制點坐標(biāo)失都。endx, endy
表示結(jié)束點坐標(biāo)柏蘑。
- 貝塞爾曲線可以幫我們獲得更加多變的曲線內(nèi)容赢底。
示例:
c.beginPath()
c.moveTo(20,20);
// 將控制點設(shè)置在線段中間,
c.quadraticCurveTo(60, 80, 100, 20)
c.stroke()
示例圖:
除了這兩種曲線粹庞,還有三次貝塞爾曲線咳焚。小伙伴們可以自己試驗下,與二次貝塞爾曲線不同的是添加了一組控制點庞溜。
8. 事件
作為canvas
中唯二的兩個可以獲取到當(dāng)前圖形信息的事件革半。isPointInPath和isPointInStroke
的作用不可小覷。在很多針對圖形的操作我們都需要用到這個方法流码。
方法也是比較簡單又官。
-
isPointInPath(x, y)
接收兩個參數(shù),一個x坐標(biāo)
一個y坐標(biāo)
漫试,判斷當(dāng)前坐標(biāo)是否在圖形之內(nèi)六敬。 -
isPointInStroke(x, y)
接收兩個參數(shù),一個x坐標(biāo)
一個y坐標(biāo)
驾荣,判斷當(dāng)前坐標(biāo)是否在空心圖形邊框上外构。
9. 將canvas轉(zhuǎn)換為圖片 -- toDataURL
最后一個來分享下如何將我們繪制好的圖形保存下來。對之后的分享自己繪制的圖形播掷,在其他內(nèi)容上顯示等等等等审编,都可以用到。
將canvas
轉(zhuǎn)換為圖片歧匈,我們需要用到 toDataURL(type, encoderOptions)
垒酬,
type
可以設(shè)置我們想得到的類型。如: image/png件炉、image/jpg…………
encoderOptions
可以設(shè)置圖片的質(zhì)量伤溉。
栗子:
const url = ctx.toDataURL('image/png')
console.log(url); // data:image/png;base64,……………………
注意:
這里我們是使用的 ctx
來轉(zhuǎn)換圖片,也就是使用 canvas
這個標(biāo)簽對象來轉(zhuǎn)換妻率。
到這里我們對于 canvas
的基礎(chǔ)內(nèi)容就分享完了,從下節(jié)開始板祝,我們就要進(jìn)入到對 webgl
的學(xué)習(xí)中了宫静。
好了,今天的分享就到這里了券时,Bye~