-
驗證瀏覽器是否支持
<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。
線帽.png ctx.lineJoin
線段的連接點,取值有round、bevel和miter
,其中miter是其默認值,取值為miter時,還可以指定一個miterLimit屬性。
-
如果繪制一條真正1像素寬的線段,你必須將該線段繪制在某兩個像素之間的那個像素中(比如從
moveTo(30.5,100.5) lineTo(50.5,120.5)
),而不能將它繪制在兩個像素的交界處。像素邊界.png
-
對于save()和restore()方法,一開始有一個錯誤的理解,以為每一步都save()之后restore()就等同于command + z(或者ctrl + z),其實save()保存的只是CanvasRenderingContext2D對象的狀態以及對象的所有屬性,并不包括這個對象上繪制的圖形。官方文檔描述如下:
save()和restore()方法允許你保存和恢復一個CanvasRenderingContext2D對象的狀態。save()把當前狀態推入到繪圖堆棧中,而restore()從繪圖堆棧中的頂端彈出最近保存的狀態,并且根據這些存儲的值來設置當前繪圖狀態。
-
繪制矩形api
- fillRect(x, y, width, height):繪制一個填充的矩形
- strokeRect(x, y, width, height):繪制一個矩形的邊框
- clearRect(x, y, width, height):清除指定矩形區域,讓清除部分完全透明.經常用來清除干凈畫布,`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()方法將剪切區域設置為當前剪切區域與當前路徑的交集。在第一次調用clip()方法之前,剪切區域與整個Canvas畫布大小一致。因為clip()方法會將剪切區域設置為當前剪切區域與當前路徑的交集,所以對該方法的調用一般都是嵌入save()和restore()方法之間的。否則,剪切區域將會越變越小,這通常不是我們想要的效果。
- Canvas中的clip()方法用于從原始畫布中剪切任意形狀和尺寸。一旦剪切了某個區域,則所有之后的繪圖都會被限制在被剪切的區域內(不能訪問畫布上的其他區域)。也可以在使用clip()方法前通過使用save()方法對當前畫布區域進行保存,并在以后的任意時間通過restore()方法對其進行恢復。
- [實現探照燈效果](https:// www.w3cplus.com/canvas/clip.html)
-
ImageData操作,無論時getImageData還是putImageData都是針對畫布來說的,拿到畫布上的像素。一般可以結合drawIamge來用,先把圖片通過drawImage繪制到圖像上,然后再通過getImageData獲取像素數據,循環修改其中的data屬性,最后再通過putImageData,把修改后的imageData放回到畫布。
-
createImageData() 方法創建新的空白 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. 以指定的尺寸(以像素計)創建新的 ImageData 對象: var imgData=ctx.createImageData(width,height); // 2. 創建與指定的另一個 ImageData 對象尺寸相同的新 ImageData 對象(不會復制圖像數據): var imgData=ctx.createImageData(imageData);
-
getImageData() 方法返回 ImageData 對象,該對象拷貝了畫布指定矩形的像素數據。
// x 開始復制的左上角位置的 x 坐標。相對與canvas // y 開始復制的左上角位置的 y 坐標。 // width 將要復制的矩形區域的寬度。 // height 將要復制的矩形區域的高度。 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 規定要放回畫布的 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 規定要使用的圖像、畫布或視頻。 // 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這種直接畫出獨立區域的函數,也不會打斷當前的path.
說到beginPath,就不得不提到closePath,兩者是不是有很“緊”的聯系呢?答案是幾乎沒有關系。
closePath的意思不是結束路徑,而是關閉路徑,它會試圖從當前路徑的終點連一條路徑到起點,讓整個路徑閉合起來。但是,這并不意味著它之后的路徑就是新路徑了!
我們在上面的代碼的第一個lineTo后面加上closePath,可以發現還是得到了兩條紅線。但如果我們在第一個stroke后面加上beginPath,則會如愿得到一條黑線一條紅線。ctx.stroke(); ctx.beginPath(); // 注意啦! ctx.moveTo(100.5,40.5); ctx.lineTo(200.5,40.5) ctx.strokeStyle = '#f00'; ctx.stroke();