本文基本上能夠用來當作 canvas 的一個基本參考。基本涵蓋了全部的 canvas 內容,固然,不包括使用 canvas 來處理的高級應用。css
基本的有:css3
基本的架構爲:web
ctx.beginPath(); // 開始畫線,裏面沒有任何參數 ctx.moveTo(x,y); // 定義起始點 ctx.lineTo(x,y); // 定義過程點 // 還能夠定義線寬,線的顏色 ctx.stroke(); // 開始劃線,裏面沒任何參數
// 簡單就是 ctx.moveTo(x,y) ctx.lineTo(x,y)
控制線寬算法
ctx.lineWidth = 20; // 單位默認爲 px
線顏色定義可使用:chrome
ctx.strokeStyle = "#fff";
定義線兩端的格式爲:canvas
context.lineCap = 'butt';
該屬性有 3 個取值:butt,round,square。分別爲:數組
用來描述,多個路徑之間的鏈接方式。基本取值有:round,bevel,miter。瀏覽器
context.beginPath(); context.moveTo(379, 150); context.lineTo(429, 50); context.lineTo(479, 150); context.lineJoin = 'bevel'; context.stroke();
詳情爲:架構
曲線和線段
基本區現有: 弧線,二次曲線,貝塞爾曲線。ide
基本格式爲:
ctx.arcTo(cx1, cy1, x2, y2, radius);
一樣,使用 moveTo 或者 lineTo 肯定第一個起始點。
context.beginPath(); context.moveTo(100, 225); // P0 context.arcTo(228, 40, 530, 70, 89); // P1, P2 and the radius context.lineTo(530, 70); // P2 context.stroke();
上面,P2 點用到了 lineTo。 這有什麼影響嗎?有的。
若是沒定義 lineTo,圓弧可能並不會過到 P2 點,由於圓弧實際的算法爲:
它只會肯定最終圓弧的範圍的大小,並不會關注 P2 點是否鏈接。若是沒定義 lineTo 的話,結果爲:
該是用來畫二次曲線的:
ctx.quadraticCurveTo(cpx, cpy, x, y);
他一般結合 moveTo
來找到 3 個點,肯定二次函數。
ctx.beginPath(); ctx.moveTo(50,20); // x 軸上的點 (50,20) ctx.quadraticCurveTo(230, 30, 50, 100); // 控制點爲 (230,30)。 // 另外 x 軸上的點爲 (50,100) ctx.stroke();
該 tag 是用來畫貝塞爾曲線的,即經過定義 4 個點,便可肯定,線的形狀,具體格式爲:
// 這裏定義了兩個控制點,一個基準點 ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
上面說到 4 個點,還有一個點是經過 moveTo 來定義的。基本格式爲:
ctx.beginPath(); ctx.moveTo(50,20); ctx.bezierCurveTo(230, 30, 150, 60, 50, 100); ctx.stroke();
如圖:
實際計算方法是取中點,而後取過中點的切線。
基本的簡單圖形有:,圓,橢圓,自定義圖形.
圖形方面一般是結合,ctx.fill() 來進行觸發渲染的操做。
該API 用來在 canvas 上畫一個。
// 基本格式爲 ctx.rect(x, y, width, height); ctx.fill(); // 或者使用二者的結合屬性 ctx.fillRect(x, y, width, height);
看 API 應該很容易就知道,這個是用來幹啥的了。
rect 默認顏色是 black
。固然,你也能夠經過使用 fillStyle
來顯示的改變顏色。
ctx.fillStyle = "green"; ctx.fillRect(10, 10, 100, 100);
上面那種形式,是用來畫圖形內容,接着,咱們可使用 strokeRect() 來畫一個矩形邊框使用。
基本格式爲:
ctx.strokeRect(x, y, width, height);
實際畫法。
ctx.strokeStyle = "green"; ctx.strokeRect(10, 10, 100, 100);
這裏,直接使用 stroke 便可,不須要在顯示觸發渲染啥的了。畫邊框,固然可使用 line 相關的屬性,好比,定義線寬。
ctx.lineWidth = 5;
實際上,結合 rect 也能夠來畫一個矩形框:
context.beginPath(); context.rect(188, 50, 200, 100); context.fillStyle = 'yellow'; context.fill(); context.lineWidth = 7; context.strokeStyle = 'black'; context.stroke(); // 觸發畫邊框的效果
基本格式爲:
// 默認爲逆時針 ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);
startAngle 是從 x 軸正方向,順時針計算角度。
詳細demo:
ctx.arc(75, 75, 50, 0, 2 * Math.PI); // 順時針畫圓 ctx.arc(75, 75, 50, 0, 2 * Math.PI,false);
好比,另外畫一個半圓。
context.beginPath(); context.arc(288, 75, 70, 0, Math.PI, false); context.closePath(); // 封閉圖形 context.lineWidth = 5; context.fillStyle = 'red'; context.fill(); context.strokeStyle = '#550000'; context.stroke();
這個 API 是最近提出來的,比較新。因此,兼容性須要考慮。基本格式爲:
// x,y 肯定長軸,短軸的位置 // rotation 按照 x 軸正方向,按照 anticlockwise 的設置進行旋轉,也是弧度制 // startAngle,endAngle 也是按照 x 軸正方向來的 ctx.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise);
他的角度表示都是 弧度制(radians)。
看個實例:
ctx.beginPath(); ctx.ellipse(100, 100, 50, 75, 45 * Math.PI/180, 0, 2 * Math.PI); ctx.stroke();
圖爲:
固然,你也可使用 fill 等,來填充相關顏色。
若是你想畫一個自定義圖形的話,須要結合 line 相關的標籤。最後使用 closePath() 來顯示封閉圖形。
closePath API 的實際做用是: 當你當前的點已經和起始點重合,那麼 do nothing。不然,將當前點和起始點用直線鏈接起來,構成封閉圖形,這樣纔可能使用 fill 相關來進行填充。
var canvas = document.getElementById('myCanvas'); var context = canvas.getContext('2d'); // begin custom shape context.beginPath(); context.moveTo(170, 80); context.bezierCurveTo(130, 100, 130, 150, 230, 150); context.bezierCurveTo(250, 180, 320, 180, 340, 150); context.bezierCurveTo(420, 150, 420, 120, 390, 100); context.bezierCurveTo(430, 40, 370, 30, 340, 50); context.bezierCurveTo(320, 5, 250, 20, 250, 50); context.bezierCurveTo(200, 5, 150, 20, 170, 80); // complete custom shape context.closePath(); context.lineWidth = 5; context.strokeStyle = 'blue'; context.stroke();
最後必定要記得使用 closePath() 這樣,才能達到完整圖形的效果。
關於填充有:基本顏色填充,漸變填充,圖片填充。基本的顏色填充會涉及到兩個,一個是 fillStyle,還有一個是 strokeStyle。兩個的基本形似是如出一轍的:
// 填充基本顏色值,好比 #fff ctx.fillStyle = color; // 填充漸變值,好比 createLinear 建立的漸變等 ctx.fillStyle = gradient; // 一般用來貼圖用的值 ctx.fillStyle = pattern;
這個就不過說了,就是填 RGB 值。
ctx.fillStyle = "blue";
漸變色有兩種,一個是線性漸變:createLinearGradient(),一個是中心漸變:createRadialGradient()。 他們可使用一個共同的 API : addColorStop()。來設置間隔色。基本格式爲:
addColorStop(offset, color);
offset: 爲 [0,1] 之間的數
color: rgb 的值
var gradient = ctx.createLinearGradient(0,0,200,0); gradient.addColorStop(0,"green"); gradient.addColorStop(1,"white"); ctx.fillStyle = gradient; ctx.fillRect(10,10,200,100);
線性漸變的內容是:
ctx.createLinearGradient(x0, y0, x1, y1);
兩個點肯定一條直線,而後將顏色按照這個線段進行漸變。
實例:
代碼爲:
gradient.addColorStop(0,'red'); gradient.addColorStop(1,'black'); ctx.fillStyle=gradient; ctx.fillRect(0,0,320,320);
中心漸變內容爲:
ctx.createRadialGradient(x0, y0, r0, x1, y1, r1);
以及上就是兩個圓,而後按照順序,將顏色漸變,固然中間也能夠添加多段。
實例:
代碼爲:
let gradient = ctx.createRadialGradient(200,200,0,200,200,160); gradient.addColorStop(0,'red'); gradient.addColorStop(1,'white'); ctx.fillStyle=gradient; ctx.arc(200,200,160,0,2*Math.PI); ctx.fill();
這一塊應該算是 canvas 牛逼的地方,可以和圖形相關的元素結合起來的關鍵點。格式爲:
ctx.createPattern(image, repetition);
image: 該類型的取值有不少,好比 image,video,cavnas,imageData,blob 等。
HTMLImageElement (< img>)
HTMLVideoElement (< video>)
HTMLCanvasElement (< canvas>)
CanvasRenderingContext2D
ImageBitmap
ImageData
Blob
repetition:該取值內容就很簡單,至關於 background 同樣,用來設置圖片的重複形式。
repeat (默認值)
repeat-x
repeat-y
no-repeat
這裏就舉一個貼圖的列子:
// FROM MDN var img = new Image(); img.src = 'https://mdn.mozillademos.org/files/222/Canvas_createpattern.png'; img.onload = function() { var pattern = ctx.createPattern(img, 'repeat'); ctx.fillStyle = pattern; ctx.fillRect(0,0,400,400); };
圖片處理相關的 API 有不少,這裏先說最基本的,drawImage()。它有 3 種基本形式:
void ctx.drawImage(image, dx, dy); void ctx.drawImage(image, dx, dy, dWidth, dHeight); void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
分別說一下:
void ctx.drawImage(image, dx, dy);
簡單的 3 個參數,就用來肯定圖片在 canvas 上的位置,不進行任何縮放。
基本格式爲:
void ctx.drawImage(image, dx, dy, dWidth, dHeight);
經過, dWidth 和 dHeight 來肯定在 canvas 中繪製的大小,能夠放大和縮小。
代碼爲:
let img = new Image(); img.onload = function(){ ctx.drawImage(img,20,20,150,100); } img.src = "...";
基本格式爲:
void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
其中,sx,sy,sWidth,sHeight 用來肯定在原來圖片上,截取圖像的區域。
具體代碼爲:
let img = new Image(); img.onload = function(){ ctx.drawImage(img,20,20,60,95,60,60,100,200); } img.src = "...";
在 canvas 裏,還有顯示文字的一個 trick 。文字方面的話,沒什麼特別的就是基本的 style, szie ,color 等。 通常結合 fillText/stokeText API 一塊兒使用,進行繪製。這裏兩個 API 的區別也很普通,就是簡單的 填充實心字體 和 邊界字體。
context.font = 'italic 40pt Calibri'; context.fillText('Hello World!', 150, 100);
先簡單說一下,這兩個 API。他們的格式,基本上是同樣的:
ctx.strokeText(text, x, y [, maxWidth]);
x,y 用來肯定 text 的左下角起始點。很重要,是左下角!
maxWidth: 用來肯定 text 渲染的寬度,若是字體大了,則會自動縮小,不會換行。
代碼爲:
ctx.font="20px serif"; ctx.strokeText("I dont Know how to Do",20,20,200);
定義一個最簡單的字體,使用的是:
ctx.font=value;
value 的值,就是通常的 css font 屬性的值。默認爲: 10px sans-serif
ctx.font = "48px serif";
這裏,還可使用比較新的 API FontFace() 來使用在線字體:
var f = new FontFace("font-name", "url(x)"); f.load().then(function() { ctx.font="20px font-name"; ctx.fillText("ABC",100,100); });
字體的顏色相關和上面圖形同樣,一樣使用的是 fillStyle
和 strokeStyle
這裏就不贅述了。
定義粗細的話,一樣使用 lineWidth 便可。
基本格式爲:
// 默認爲 start ctx.textAlign = "left" || "right" || "center" || "start" || "end";
這裏,並非用來定義字體在 canvas 中的排列位置,而是用來定義,基準點相對於字體的位置。
經常使用的就是居中佈局:
代碼爲:
ctx.font="20px serif"; ctx.textAlign='center'; ctx.strokeText("I dont Know how to Do",200,200);
其他的取值,好比 left,right 都是相對於該點進行繪製的。
好比,取 right/end:
基本格式爲:
// 默認值爲: ideographic ctx.textBaseline = "top" || "hanging" || "middle" || "alphabetic" || "ideographic" || "bottom";
該屬性和 baseline 差很少,是用來肯定基線在字體的哪個位置。 在定位的時候,線是不動的,動的是字。
詳情參考:
若是想知道當前字體的寬度,可使用 measureText
API 來完成。基本使用也很簡單:
var text = ctx.measureText("foo"); // TextMetrics object text.width; // 16;
固然,這個屬性返回的對象上面,還掛載了不少其餘測量值,不過兼容性比較差。關鍵點在於,能夠結合該 API 來畫出分行的字體內容。簡單的說來就是經過將字符串拆分,判斷渲染字符串是否超過本行的寬度,進而決定是否將標識點 y 軸值加 lineheight。
簡單看個算法:
function wrapText(context, text, x, y, maxWidth, lineHeight) { // 經過使用 ' ' 進行字符的拆分 (這裏就不針對中文了) var words = text.split(' '); var line = ''; for(var n = 0; n < words.length; n++) { // 判斷行 var testLine = line + words[n] + ' '; // 測量渲染的寬度 var metrics = context.measureText(testLine); var testWidth = metrics.width; if (testWidth > maxWidth && n > 0) { // 超過,則下一該行 context.fillText(line, x, y); line = words[n] + ' '; y += lineHeight; } else { line = testLine; } } context.fillText(line, x, y); } var canvas = document.getElementById('myCanvas'); var context = canvas.getContext('2d'); var maxWidth = 400; var lineHeight = 25; var x = (canvas.width - maxWidth) / 2; var y = 60; var text = 'All the world \'s a stage, and all the men and women merely players. They have their exits and their entrances; And one man in his time plays many parts.'; context.font = '16pt Calibri'; context.fillStyle = '#333'; wrapText(context, text, x, y, maxWidth, lineHeight);
關於變化,最基本的就是 translate, scale,skew 等。在 canvas 中,這些就是針對於 canvas 座標系來的。
這是用來進行原點平移的變化。基本格式爲:
ctx.translate(x, y);
x: 當前座標系在 x 軸向的移動方向
y:當前座標在 y 軸向的移動方向
固然,還有對應的 2D 變換矩陣,這和 transform 屬性同樣。可使用下列的變換:
ctx.setTransform(1, 0, 0, 1, x, y);
這是用來旋轉座標系的。基本格式爲:
// 裏面的參數是弧度,可使用 Math.PI 來進行轉換 ctx.rotate(angle);
例如:
ctx.rotate(45 * Math.PI / 180); ctx.fillRect(70,0,100,30);
當在旋轉時,在矩陣中是根據 sin 函數來表示的旋轉角度的值。
ctx.setTransform(cosθ,sinθ,-sinθ,cosθ,0,0) // 就是 cs-sc
縮放座標系,基本格式爲:
ctx.scale(x, y);
它表達的意思是:
x: 將 x 軸放大/縮小 x 倍。即,設置的像素值會乘以該 x
值.
y: 將 y 軸放大/縮小 y 倍。即,設置的像素值會乘以該 y
值.
看個 demo:
ctx.scale(10, 3); ctx.fillRect(10,10,10,10); // 最後的結果就是,在 (100,30) 點,畫出 width: 100,height: 30 的矩形。
另外,你還能夠利用這個屬性做顛倒:
ctx.scale(-1, 1); // x 軸對稱 ctx.font = "48px serif"; ctx.fillText("Hello world!", -320, 120); // x 軸的值須要設爲負數 ctx.setTransform(1, 0, 0, 1, 0, 0); // 還原座標
它對應於矩陣的表達就是:
setTransform(A, 0, 0, B, 0,0); // X 軸放大 A 倍 // Y 軸放大 B 倍
矩陣變換的 API 和 css3 動畫中的沒啥區別:
ctx.setTransform(a, b, c, d, e, f);
最常使用的是用來進行座標還原。由於,它每一次變換都是覆蓋掉上一次變化,因此,還原座標常使用:
ctx.setTransform(1,0,0,1,0,0);
不過,除了這個方法外,其餘變換都是基於已經變化後的座標來變換的。
該 API 和 setTransform 有些不一樣。setTransform 至關於重置,而 transform 會基於前一個變換結果,接着進行變換。它的使用方式和 setTransform 差很少。
ctx.transform(a, b, c, d, e, f);
至關於就是 setTransform(1,0,0,1,0,0)
的封裝。
ctx.resetTransform();
在 canvas 裏面,由於有時候操做比較多,可能會形成來回變換座標。這時候,就可使用 canvas 裏面的狀態管理。save
& restore
,這兩個方法至關於 stack 的 push
& pop
方法。一個入棧,一個出棧。那麼,這些狀態會保存什麼呢?
變形操做,基本的移動,縮放,旋轉,矩陣變換等。
裁剪區域
dash list
以及相關的筆觸,填充狀態。好比: strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin。
不過,它僅僅只是做爲一個狀態進行保存的。當結合 restore 一塊兒,纔會發揮它應該有的效果。
ctx.save(); ctx.fillStyle = "green"; ctx.fillRect(10, 10, 100, 100); ctx.restore(); // 恢復原始的 fillStyle 內容 ctx.fillRect(150, 75, 100, 100);
在 canvas 中的層合併,涉及到陰影,裁剪等效果。
關於 canvas 中的陰影涉及到 4 個API。
shadowBlur
shadowColor
shadowOffsetX
shadowOffsetY
分別介紹一下:
這是用來添加陰影的,基本格式爲:
ctx.shadowBlur = level;
level 的值默認爲 0,表示不存在陰影。而且,不能取 Negative, Infinity or NaN。level 表示的意義只在於,規定陰影模糊的範圍而已。須要注意,一旦你設置了 shadoeBlur,那麼接下來,在 canvas 上畫的全部元素,都會帶上陰影的效果,即便是透明元素。因此,通常狀況下能夠手動回撤:
ctx.shadowBlur = 0;
或者,結合 save 和 restore 來進行狀態回撤。
ctx.save(); ctx.shadowBlur = 5; ctx.fillRect(0,0,400,400); ctx.restore();
用來設置陰影的顏色值,默認是不透明的黑色。
基本格式爲:
// color 默認爲 「black」 ctx.shadowColor = color;
這個實際上和 box-shadow 設置的陰影效果是同樣的,用來定義陰影相對於原始圖形的偏移量。基本格式爲:
// offset 默認值爲 0,至關於取 canvas 上的像素值 // 能夠爲負值,但不能取 Infinity or NaN ctx.shadowOffsetX = offset;
實例爲:
// 在 x 軸上移動陰影 ctx.shadowOffsetX = 10; // 在 Y 軸上移動陰影 ctx.shadowOffsetY = 10;
在 canvas 裏面,定義顏色通常只支持 RGB 的格式,若是想要設置透明顏色的話,則須要使用 globalAlpha
屬性值。基本格式爲:
// value 爲 [0.0,1.0] // 默認值爲 0.0,表示不透明 ctx.globalAlpha = value;
看個 demo:
ctx.globalAlpha = 0.5; ctx.fillStyle = "blue"; ctx.fillRect(10, 10, 100, 100); ctx.fillStyle = "red"; ctx.fillRect(50, 50, 100, 100);
在 canvas 裏面,通常使用的是 clip
API 來進行對屏幕的裁剪。基本格式爲:
// 最經常使用 void ctx.clip(); // fillRule 主要有兩種,下面再解釋 void ctx.clip(fillRule); // 這裏就是將須要畫的路徑,當參數傳到 clip 裏 void ctx.clip(path, fillRule);
先解釋一下 fillRule:
經常使用的 fillRule 有兩種,一種是 nonzero,一種是 even-odd 。主要做用就是用來判斷重疊區域是否屬於裁剪區域。ok,什麼叫重疊區域呢?就是:
這種狀況下,canvas 怎麼判斷這樣的區域是否重疊呢?
默認的算法是 nonzero。
nonzero
它具體的過程是,在重疊區域中,選擇一個 P 點,而後隨機的按照一個方向,作無限長的射線,檢測該線和邊界的交叉點,判斷接觸位置是 順時針仍是逆時針。若是爲順時針則 -1,若是爲逆時針則 +1。統計最終的結果,若是爲 0 則說明,該區域在外部,不然在內部。
因此,上面的結果是 -2,不是 0,則表示在內部。
even-odd rule
該算法主要約定的是,統計射線和邊界相交的次數,若是爲偶數,則表示不在內部,若是爲奇數,則表示在內部。
因此,根據該算法,上面的結果爲 2 (偶數),則不在內部。
不過,在大多數狀況下,這你都不須要過多關心。接下來,咱們來實踐一下,如何繪製裁剪區域。這裏,咱們就能夠將 clip
方法想象爲 stroke 方法。在 clip 前,先手動繪製路徑,繪製完成後,即可以觸發 clip 進行裁剪就 ok 了。
ctx.beginPath(); ctx.ellipse(100,100,30,50,0,0,2*Math.PI); ctx.clip(); ctx.fillRect(100,100,30,50);
實際樣式爲:
圖層重疊用到的 API 爲: globalCompositeOperation
。它的做用主要是用來規定,兩個重疊圖層繪製的效果。基本格式爲:
globalCompositeOperation = type
基本的取值,能夠參考: globalCompositeOperation - 取值內容
canvas 中的圖像處理內容很少,基本上有 3 個API:createImageData(),putImageData(),getImageData()。第一個就是用來截屏用的,第二/三個就是用來獲取圖片的基本信息,在關於 image 有個比較重要的概念就是 imagedata。
imageData:實際上就是完整的圖片內容。它是底層像素的上層表示,其掛載了 3 個屬性。
width: 圖片的寬
height:圖片的高
data: 是 Uint8ClampedArray
格式,實際上一個一維數組,按順序,每一個像素點佔 4 位,裏面包含了 RGBA 的內容,每一位都是 0-255 大小的數。最後透明度有點特殊,取值爲 [0-255] 表示不透明。若是須要用到 css 的 rgba 中,須要 /255
。例如: [0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255]
,4個點。
最常獲取到 imagedata 就是經過 createImageData
。注意,經過 image 是不能獲取 imagedata 的,imagedata 只能經過 createImageData 來獲取和建立。
ctx.rect(10, 10, 100, 100); ctx.fill(); let imagedata = ctx.createImageData(100, 100);
用來手動建立一個空圖片內容,默認的像素都是透明的黑色,基本格式爲:
ImageData ctx.createImageData(width, height); ImageData ctx.createImageData(imagedata);
width/height:用來設置當前 imgObj 的大小。
imagedata:得到一個已知 imgObj 的大小,注意這裏不是複製,只是 copy imagedata 的 width/height。
目前來講,它的用途,還不知道在哪裏~
該 API 經常用來做爲圖片分析,由於它能夠直接獲取 canvas 上像素的內容,而後進行相關操做。基本格式爲:
ctx.getImageData(x, y, width, height);
x,y 用來指定截取像素的起始點
widht/height 用來指定截取像素點的寬/高
例如:
ctx.fillRect(0,0,200,200); let new_one = ctx.getImageData(0,0,2,2);
該屬性最大的用處在於,用來做爲取色器。經過,傳入 canvas 裏的座標,來獲取指定位置的顏色值。
ctx.fillRect(0,0,200,200); let new_one = ctx.getImageData(0,0,1,1); let backColor = function(data){ return `(${data[0]},${data[1]},${data[2]},${data[3]/255})`; }
該屬性經常用來做爲,像素的填寫。基本格式爲:
void ctx.putImageData(imagedata, dx, dy); void ctx.putImageData(imagedata, dx, dy, startX, startY, width, height);
主要所一下第二種形式吧:
dx/y 表明在 canvas 上繪製的繪製
startX/Y 表示相對於圖片其實的位置
width/height 表示獲取的寬/高
具體的含義爲:
ctx.fillRect(0,0,100,100); var imagedata = ctx.getImageData(0,0,100,100); // 獲取部分圖像信息 ctx.putImageData(imagedata, 150, 0, 20, 20, 25, 25); ctx.strokeRect(150,0,100,100);
該經常用來做爲放大預覽,灰度處理,導出圖片等。詳情能夠參考: 圖片像素處理。總而言之,putImageData 常做爲處理圖片自己,而 drawImage 經常使用於建立另一新的 canvas。
這應該算一種快速生成圖片格式的方法吧。該是經過算法,將圖像中的像素點轉化爲序列值(也就是文本),咱們能夠直接將文本放入 img.src 中,便可顯示圖片。
在 canvas 中生成 URI 須要使用:
canvas.toDataURL(type, encoderOptions);
該 API 是直接掛在到 canvas 下的。
type: 用來設置導出圖片類型,默認爲:image/png。可選值有:image/jpeg,image/webp(chrome支持)。
encoderOptions[Number]:用來設置壓縮比。只針對於 image/jpeg or webp 有用。一般取值爲 0-1。默認值爲 0.92。
DataURI 的基本格式爲:
data:[<mediatype>][;base64],<data> // 例如: data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ9oADAMBAAIRAxEAPwD/AD/6AP/Z
生成的 DataURI 是根據 canvas 的大小來肯定的。
var canvas = document.getElementById("canvas"); // canvas size: 5x5 var dataURL = canvas.toDataURL(); // 生成的大小爲 5x5
不過並非,任何圖片都能生成 DataURI 的,有些瀏覽器因爲內存的限制,對 DataURI 的長度也會有所限制。例如:Opera 限制爲 65000 characters。
使用 Canvas 來作動畫,咱們須要瞭解幕布的蓋簾--擦除,繪製。基本的 API 有: clearRect, requestAnimation
該 API 用來清空一塊幕布,基本格式爲:
ctx.clearRect(x, y, width, height);
用來清除指定區域的內容。
x,y:用來指定區域的起始位置
width,height:指定區域的寬高
通常來講,一般是用來清除整個 canvas 內容。
ctx.clearRect(0, 0, canvas.width, canvas.height);
主要仍是依靠循環調用 RAF,來實現流暢動畫。看一個 demo
var sun = new Image(); var moon = new Image(); var earth = new Image(); function init(){ // online earth.src = 'https://mdn.mozillademos.org/files/1429/Canvas_earth.png'; sun.src = 'https://mdn.mozillademos.org/files/1456/Canvas_sun.png'; moon.src = 'https://mdn.mozillademos.org/files/1443/Canvas_moon.png'; // local earth.src = 'Canvas_earth.png'; sun.src='Canvas_sun.png'; window.requestAnimationFrame(draw); } function draw(){ let canvas = document.getElementsByTagName('canvas')[0], ctx = canvas.getContext('2d'), width = canvas.width, height = canvas.height; // ctx.globalCompositeOperation = 'destination-over'; ctx.clearRect(0,0,width,height); ctx.drawImage(sun,0,0,width,height); ctx.fillStyle= 'rgba(0,0,0,0.4)'; ctx.strokeStyle = 'rgba(0,50,50,0.5)'; ctx.arc(width/2,height/2,width/3,0,2*Math.PI); ctx.stroke(); // ctx.fill(); ctx.save(); //earth let date = new Date(); ctx.translate(width/2,height/2); // 公轉 ctx.rotate ((2*Math.PI)*1*(date.getSeconds()/60 + date.getMilliseconds()/60000) ); ctx.translate(width/3,0); // 自轉 ctx.rotate ((2*Math.PI)*25*(date.getSeconds()/60 + date.getMilliseconds()/60000) ); ctx.drawImage(earth,-earth.width/2,-earth.height/2); ctx.save(); ctx.translate(20,0); ctx.drawImage(moon,-moon.width/2,-moon.height/2); ctx.restore(); ctx.restore(); window.requestAnimationFrame(draw); } init();