-
驗證瀏覽器是否支持
<canvas id="myCanvas" width="400" height="400"> Your browser does not support HTML5 Canvas. </canvas>
function canvasAPP () { var myCanvas = document.getElementById('myCanvas'); if (!myCanvas || !myCanvas.getContext) { return; } // 這里開始繪制 var ctx = myCanvas.getContext('2d'); function drawScreen () { // ... } drawScreen(); }
-
繪制線段
ctx.strokeStyle
用于設置畫筆繪制路徑的顏色、漸變和模式ctx.lineWidth
定義繪制線條的寬度ctx.beginPath()
開始一個新的繪制路徑ctx.moveTo(x,y)
移動畫筆到指定的坐標點(x,y)嘶朱,該點就是新的子路徑的起始點ctx.lineTo(x,y)
使用直線邊接當前端點和指定的坐標點(x,y)ctx.stroke()
沿著繪制路徑的坐標點順序繪制直線ctx.closePath()
如果當前的繪制路徑是打開的,則關閉掉該繪制路徑ctx.setLineDash([])
繪制虛線步鉴,數組內可以傳一個元素恰起,兩個或者三個分別表示線段,間隔大小-
ctx.lineCap
線帽,取值有butt交洗、round和square
愧哟,其中默認的值是butt奥吩。
ctx.lineJoin
線段的連接點哼蛆,取值有round、bevel和miter
,其中miter是其默認值霞赫,取值為miter時腮介,還可以指定一個miterLimit屬性。
-
如果繪制一條真正1像素寬的線段端衰,你必須將該線段繪制在某兩個像素之間的那個像素中(比如從
moveTo(30.5,100.5) lineTo(50.5,120.5)
)叠洗,而不能將它繪制在兩個像素的交界處。
-
對于save()和restore()方法旅东,一開始有一個錯誤的理解灭抑,以為每一步都save()之后restore()就等同于command + z(或者ctrl + z),其實save()保存的只是CanvasRenderingContext2D對象的狀態(tài)以及對象的所有屬性抵代,并不包括這個對象上繪制的圖形腾节。官方文檔描述如下:
save()和restore()方法允許你保存和恢復一個CanvasRenderingContext2D對象的狀態(tài)。save()把當前狀態(tài)推入到繪圖堆棧中荤牍,而restore()從繪圖堆棧中的頂端彈出最近保存的狀態(tài)案腺,并且根據這些存儲的值來設置當前繪圖狀態(tài)。
-
繪制矩形api
- fillRect(x, y, width, height):繪制一個填充的矩形
- strokeRect(x, y, width, height):繪制一個矩形的邊框
- clearRect(x, y, width, height):清除指定矩形區(qū)域康吵,讓清除部分完全透明.經常用來清除干凈畫布劈榨,`ctx.clearRect(0,0,myCanvas.width,myCanvas.height);
- rect(x, y, width, height):也是Canvas中路徑的一個方法,需要配合fill()和stroke()晦嵌。
function drawScreen () { ctx.strokeStyle = '#000'; ctx.fillStyle = '#9f9' ; ctx.lineWidth = 4; // 繪制 ctx.beginPath(); ctx.rect(30,30,200,200); ctx.stroke(); // 繪制 ctx.beginPath(); ctx.rect(300,30,200,200); ctx.fill(); // 繪制既有邊框又填充鞋既,注意因為lineWidth為4,fill方法的值大小 ctx.strokeRect(240,10,100,100); ctx.fillRect(242,12,96,96); }
-
在Canvas中耍铜,CanvasRenderingContext2D對象提供了兩個方法(arc()和arcTo())來繪制圓和圓弧邑闺。其中arc()即可繪制弧線,圓棕兼,也可以繪制扇形陡舅,但arcTo()僅能繪制出弧線。但arcTo()可以更輕易的幫助我們實現帶圓角的矩形伴挚。
-
arc(x, y, radius, startRad, endRad, [anticlockwise])
坐標點(x,y)為圓心靶衍、半么為radius的圓上的一段弧線。這段弧線的起始弧度是startRad茎芋,結束弧度是endRad颅眶。這里的弧度是以x軸正方向為基準、進行順時針旋轉的角度來計算田弥。其中anticlockwise表示arc()繪制圓或圓弧是以順時針還是逆時針方向開始繪制涛酗。如果其值為true表示逆時針,如果是false表示為順時針。該參數是一個可選參數商叹,如果沒有顯式設置燕刻,其值是false(也是anticlockwise的默認值)。 -
arcTo(x1, y1, x2, y2, radius)
arcTo()方法將利用當前端點剖笙、端點一(x1, y1)和端點二(x2, y2)這三點所形成的夾角卵洗,然后繪制一段與夾角的兩邊相切并且半徑為radius的圓上的弧線∶诌洌弧線的起點就是當前端點所在邊與圓的切點过蹂,弧線的終點就是商端點二(x2,y2)所在邊與圓的切點,并且繪制的弧線是兩個切點之間長度最短的那個圓弧聚至。此外榴啸,如果當前端點不是弧線起點,arcTo()方法還將添加一條當前端點到弧線起點的直線線段晚岭。
-
-
Canvas坐標變換有移動鸥印、旋轉和縮放
- ctx.translate(x, y) :translate方法接受兩個參數。x是左右偏移量坦报,y是上下偏移量库说。當偏移量操作出Canvas的width或height時,坐標將會移出Canvas的畫布片择,這個時候你繪制的東西都將看不到潜的。
- ctx.rotate(angle) :rotate()方法只接受一個參數,旋轉的角度angle字管,它是順時針方向的啰挪,以弧度為單位的值。
- ctx.scale(x, y) :scale()方法接受兩個參數嘲叔。x和y分別是橫軸和縱軸的縮放因子亡呵。其縮放因子默認是1,如果比1小是縮小硫戈,如果比1大則放大锰什。在繪制了某個圖形后,可以調用ctx.scale(-1, 1)來繪制其水平鏡像或者調用ctx.scale(1, -1)來繪制其垂直鏡像(這里只是把坐標系翻轉丁逝,翻轉后還需要再繪制一遍要鏡像的圖形)汁胆。
Canvas中可以通過ctx.fillText("內容",x,y,maxWidth)繪制填充文本,ctx.strokeText()可以繪制描邊文本霜幼,另外通過ctx.textAlign和ctx.textBaseline設置所繪制文本的位置嫩码,并且使用ctx.measureText('text').width可以得到所繪制文本text的寬度值,雖然這個值并不精確
-
在Canvas中有兩個屬性globalAlpha和globalCompositeOperation來控制圖像合成操作:
- globalAlpha:設置圖像的透明度罪既。globalAlpha屬性默認值為1铸题,表示完全不透明铡恕,并且可以設置從0(完全透明)到1(完全不透明)。這個值必須設置在圖形繪制之前回挽。
- globalCompositeOperation:該屬性的值在globalAlpha以及所有變換都生效后控制在當前Canvas位圖中繪制圖形
// 上面是目標圖像(已有)没咙,下面是源圖像(新的)猩谊; // source-over 默認千劈。在目標圖像上顯示源圖像。 // source-atop 在目標圖像頂部顯示源圖像牌捷。源圖像位于目標圖像之外的部分是不可見的墙牌。 // source-in 在目標圖像中顯示源圖像。只有目標圖像內的源圖像部分會顯示暗甥,目標圖像是透明的喜滨。 // source-out 在目標圖像之外顯示源圖像。只會顯示目標圖像之外源圖像部分撤防,目標圖像是透明的虽风。 // destination-over 在源圖像上方顯示目標圖像。 // destination-atop 在源圖像頂部顯示目標圖像寄月。源圖像之外的目標圖像部分不會被顯示辜膝。 // destination-in 在源圖像中顯示目標圖像。只有源圖像內的目標圖像部分會被顯示漾肮,源圖像是透明的厂抖。 // destination-out 在源圖像外顯示目標圖像。只有源圖像外的目標圖像部分會被顯示克懊,源圖像是透明的忱辅。 // lighter 顯示源圖像 + 目標圖像。 // copy 顯示源圖像谭溉。忽略目標圖像墙懂。 // source-over 使用異或操作對源圖像與目標圖像進行組合。 ctx.globalCompositeOperation = "source-over";
-
clip()方法將剪切區(qū)域設置為當前剪切區(qū)域與當前路徑的交集扮念。在第一次調用clip()方法之前垒在,剪切區(qū)域與整個Canvas畫布大小一致。因為clip()方法會將剪切區(qū)域設置為當前剪切區(qū)域與當前路徑的交集扔亥,所以對該方法的調用一般都是嵌入save()和restore()方法之間的场躯。否則,剪切區(qū)域將會越變越小旅挤,這通常不是我們想要的效果踢关。
- Canvas中的clip()方法用于從原始畫布中剪切任意形狀和尺寸。一旦剪切了某個區(qū)域粘茄,則所有之后的繪圖都會被限制在被剪切的區(qū)域內(不能訪問畫布上的其他區(qū)域)签舞。也可以在使用clip()方法前通過使用save()方法對當前畫布區(qū)域進行保存秕脓,并在以后的任意時間通過restore()方法對其進行恢復。
- [實現探照燈效果](https:// www.w3cplus.com/canvas/clip.html)
-
ImageData操作,無論時getImageData還是putImageData都是針對畫布來說的儒搭,拿到畫布上的像素吠架。一般可以結合drawIamge來用,先把圖片通過drawImage繪制到圖像上搂鲫,然后再通過getImageData獲取像素數據傍药,循環(huán)修改其中的data屬性,最后再通過putImageData魂仍,把修改后的imageData放回到畫布拐辽。
-
createImageData() 方法創(chuàng)建新的空白 ImageData 對象。新對象的默認像素值 transparent black擦酌。
對于 ImageData 對象中的每個像素俱诸,都存在著四方面的信息,即 RGBA 值:
R - 紅色 (0-255)
G - 綠色 (0-255)
B - 藍色 (0-255)
A - alpha 通道 (0-255; 0 是透明的赊舶,255 是完全可見的)
因此 睁搭,transparent black 表示 (0,0,0,0)。
color/alpha 以數組形式存在笼平,并且既然數組包含了每個像素的四條信息园骆,數組的大小是 ImageData對象的四倍。(獲得數組大小有更簡單的辦法出吹,就是使用 ImageDataObject.data.length)遇伞。
注意:包含 color/alpha 信息的數組存儲于 ImageData 對象的 data 屬性中。// 1. 以指定的尺寸(以像素計)創(chuàng)建新的 ImageData 對象: var imgData=ctx.createImageData(width,height); // 2. 創(chuàng)建與指定的另一個 ImageData 對象尺寸相同的新 ImageData 對象(不會復制圖像數據): var imgData=ctx.createImageData(imageData);
-
getImageData() 方法返回 ImageData 對象捶牢,該對象拷貝了畫布指定矩形的像素數據鸠珠。
// x 開始復制的左上角位置的 x 坐標。相對與canvas // y 開始復制的左上角位置的 y 坐標秋麸。 // width 將要復制的矩形區(qū)域的寬度渐排。 // height 將要復制的矩形區(qū)域的高度。 var imgData=context.getImageData(x,y,width,height); // 返回的 ImageData 對象中第一個像素的 color/alpha 信息,注意這里只是第一個像素灸蟆,每個像素占數組的四個元素 red=imgData.data[0]; green=imgData.data[1]; blue=imgData.data[2]; alpha=imgData.data[3];
-
putImageData() 方法將圖像數據(從指定的 ImageData 對象)放回畫布上
// imgData 規(guī)定要放回畫布的 ImageData 對象驯耻。 // x ImageData 對象左上角的 x 坐標,以像素計炒考。 // y ImageData 對象左上角的 y 坐標可缚,以像素計。 // dirtyX 可選斋枢。水平值(x)帘靡,以像素計,在畫布上放置圖像的位置瓤帚。 // dirtyY 可選描姚。水平值(y)涩赢,以像素計,在畫布上放置圖像的位置轩勘。 // dirtyWidth 可選筒扒。在畫布上繪制圖像所使用的寬度。 // dirtyHeight 可選绊寻。在畫布上繪制圖像所使用的高度花墩。 ctx.putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight);
ImageDate對象的三個屬性
width 返回 ImageData 對象的寬度
height 返回 ImageData 對象的高度
data 返回一個對象,其包含指定的 ImageData 對象的圖像數據
-
-
圖像繪制榛斯,向畫布上繪制圖像观游、畫布或視頻
// img 規(guī)定要使用的圖像搂捧、畫布或視頻驮俗。 // sx 可選。開始剪切的 x 坐標位置允跑。 // sy 可選王凑。開始剪切的 y 坐標位置。 // swidth 可選聋丝。被剪切圖像的寬度索烹。 // sheight 可選。被剪切圖像的高度弱睦。 // x 在畫布上放置圖像的 x 坐標位置百姓。 // y 在畫布上放置圖像的 y 坐標位置。 // width 可選况木。把圖像繪制到畫布上的寬度垒拢。(伸展或縮小圖像) // height 可選。把圖像繪制到畫布上的高度火惊。(伸展或縮小圖像) ctx.drawImage(img,x,y); ctx.drawImage(img,x,y,width,height); ctx.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
-
如何把canvas畫布轉換成img圖像,[更多canvas壓縮圖片操作](http:// www.zhangxinxu.com/wordpress/2017/07/html5-canvas-image-compress-upload/)
- canvas.toDataURL()方法,注意是canvas對象調用的方法
canvas.toDataURL(mimeType, qualityArgument)
可以把圖片轉換成base64格式信息求类,純字符的圖片表示法。
其中:
mimeType表示canvas導出來的base64圖片的類型屹耐,默認是png格式尸疆,也即是默認值是'image/png',我們也可以指定為jpg格式'image/jpeg'或者webp等格式惶岭。file對象中的file.type就是文件的mimeType類型寿弱,在轉換時候正好可以直接拿來用(如果有file對象)。
qualityArgument表示導出的圖片質量按灶,只要導出為jpg和webp格式的時候此參數才有效果症革,默認值是0.92,是一個比較合理的圖片質量輸出參數兆衅,通常情況下地沮,我們無需再設定嗜浮。- canvas.toBlob()方法
canvas.toBlob(callback, mimeType, qualityArgument)
可以把canvas轉換成Blob文件,通常用在文件上傳中摩疑,因為是二進制的危融,對后端更加友好。
和toDataURL()方法相比雷袋,toBlob()方法是異步的吉殃,因此多了個callback參數,這個callback回調方法默認的第一個參數就是轉換好的blob文件信息楷怒,本文demo的文件上傳就是將canvas圖片轉換成二進制的blob文件蛋勺,然后再ajax上傳的,代碼如下:// canvas轉為blob并上傳 canvas.toBlob(function (blob) { // 圖片ajax上傳 var xhr = new XMLHttpRequest(); // 開始上傳 xhr.open("POST", 'upload.php', true); xhr.send(blob); });
-
beginPath 的重要性鸠删,從下面代碼開始
var ctx = document.getElementById('cvs').getContext('2d'); ctx.beginPath(); ctx.moveTo(100.5,20.5); ctx.lineTo(200.5,20.5); ctx.stroke(); ctx.moveTo(100.5,40.5); ctx.lineTo(200.5,40.5) ctx.strokeStyle = '#f00'; ctx.stroke();
其中的0.5是為了避免”1px線條模糊問題“抱完,你懂的。那么上面的代碼會得到什么樣的圖形呢刃泡?是不是一條黑線一條紅線呢巧娱?
從代碼上看,我們的邏輯毫無問題烘贴,但結果是我們得到的是兩條紅線禁添,并不是一黑一紅。
canvas中的繪制方法(如stroke,fill)桨踪,都會以“上一次beginPath”之后的所有路徑為基礎進行繪制老翘。比如上面的代碼里面我stroke了兩次,其實這兩次都是以第一次beginPath后的所有路徑為基礎畫的锻离。也就是說第一條路徑我們stroke了兩下铺峭,第一下是黑的,第二下是紅的纳账,所以最終也是紅的逛薇。- 不管你用moveTo把畫筆移動到哪里,只要不beginPath疏虫,那你一直都是在畫一條路徑永罚。
- fillRect與strokeRect這種直接畫出獨立區(qū)域的函數,也不會打斷當前的path.
說到beginPath卧秘,就不得不提到closePath呢袱,兩者是不是有很“緊”的聯(lián)系呢?答案是幾乎沒有關系翅敌。
closePath的意思不是結束路徑羞福,而是關閉路徑,它會試圖從當前路徑的終點連一條路徑到起點蚯涮,讓整個路徑閉合起來治专。但是卖陵,這并不意味著它之后的路徑就是新路徑了!
我們在上面的代碼的第一個lineTo后面加上closePath张峰,可以發(fā)現還是得到了兩條紅線泪蔫。但如果我們在第一個stroke后面加上beginPath,則會如愿得到一條黑線一條紅線喘批。ctx.stroke(); ctx.beginPath(); // 注意啦撩荣! ctx.moveTo(100.5,40.5); ctx.lineTo(200.5,40.5) ctx.strokeStyle = '#f00'; ctx.stroke();