1. 程式人生 > 程式設計 >JS Canvas介面和動畫效果大全

JS Canvas介面和動畫效果大全

概述

<canvas>元素用於生成影象。它本身就像一個畫布,javascript通過操作它的 API,在上面生成影象。它的底層是一個個畫素,基本上<canvas>是一個可以用javaScript操作的點陣圖(bitmap)。

它與 SVG 影象的區別在於,<canvas>是指令碼呼叫各種方法生成影象,SVG 則是一個 XML 檔案,通過各種子元素生成影象。

使用 Canvas API 之前,需要在網頁裡面新建一個<canvas>元素。

<canvas id="myCanvas" width="400" height="250">
  你的瀏覽器不支援canvas!
</canvas>

如果瀏覽器不支援這個 API,就會顯示<canvas>標籤中間的文字:“您的瀏覽器不支援 Canvas”。

每個<canvas>元素都有一個對應的CanvasRenderingContext2D物件(上下文物件)。Canvas API 就定義在這個物件上面。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

上面程式碼中,<canvas>元素節點物件的getContext()方法,返回的就是CanvasRenderingContext2D物件。

注意,Canvas API 需要getContext方法指定引數2d,表示該<canvas>節點生成 2D 的平面圖像。如果引數是webgl,就表示用於生成 3D 的立體圖案,這部分屬於 WebGL API。

按照用途,Canvas API 分成兩大部分:繪製圖形和影象處理。

Canvas API:繪製圖形

Canvas 畫布提供了一個作圖的平面空間,該空間的每個點都有自己的座標。原點(0,0)位於影象左上角,x軸的正向是原點向右,y軸的正向是原點向下。

路徑

以下方法和屬性用來繪製路徑。

  • CanvasRenderingContext2D.beginPath():開始繪製路徑。
  • CanvasRenderingContext2D.closePath():結束路徑,返回到當前路徑的起始點,會從當前點到起始點繪製一條直線。如果圖形已經封閉,或者只有一個點,那麼此方法不會產生任何效果。
  • CanvasRenderingContext2D.moveTo():設定路徑的起點,即將一個新路徑的起始點移動到(x,y)座標。
  • CanvasRenderingContext2D.lineTo():使用直線從當前點連線到(x,y)座標。
  • CanvasRenderingContext2D.fill():在路徑內部填充顏色(預設為黑色)。
  • CanvasRenderingContext2D.stroke():路徑線條著色(預設為黑色)。
  • CanvasRenderingContext2D.fillStyle:指定路徑填充的顏色和樣式(預設為黑色)。
  • CanvasRenderingContext2D.strokeStyle:指定路徑線條的顏色和樣式(預設為黑色)。
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.beginPath();
ctx.moveTo(100,100);
ctx.lineTo(200,200);
ctx.lineTo(100,200);

上面程式碼只是確定了路徑的形狀,畫布上還看不出來,因為沒有顏色。所以還需要著色。

ctx.fill();
// 或者
ctx.stroke();

上面程式碼中,這兩個方法都可以使得路徑可見。fill()在路徑內部填充顏色,使之變成一個實心的圖形;stroke()只對路徑線條著色。

這兩個方法預設都是使用黑色,可以使用fillStyle和strokeStyle屬性指定其他顏色。

ctx.fillStyle = "red";
ctx.fill();
// 或者
ctx.strokeStyle = "red";
ctx.stroke();

上面程式碼將填充和線條的顏色指定為紅色。

線型

以下的方法和屬性控制線條的視覺特徵。

  • CanvasRenderingContext2D.lineWidth:指定線條的寬度,預設為 1.0。
  • CanvasRenderingContext2D.lineCap:指定線條末端的樣式,有三個可能的值:butt(預設值,末端為矩形)、round(末端為圓形)、square(末端為突出的矩形,矩形寬度不變,高度為線條寬度的一半)。
  • CanvasRenderingContext2D.lineJoin:指定線段交點的樣式,有三個可能的值:round(交點為扇形)、bevel(交點為三角形底邊)、miter(預設值,交點為菱形)。
  • CanvasRenderingContext2D.miterLimit:指定交點菱形的長度,預設為 10。該屬性只在lineJoin屬性的值等於miter時有效。
  • CanvasRenderingContext2D.getLineDash():返回一個數組,表示虛線裡面線段和間距的長度。
  • CanvasRenderingContext2D.setLineDash():陣列,用於指定虛線裡面線段和間距的長度。
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.beginPath();
ctx.moveTo(100,200);

ctx.lineWidth = 3;
ctx.lineCap = "round";
ctx.lineJoin = "round";
ctx.setLineDash([15,5]);
ctx.stroke();

上面程式碼中,線條的寬度為 3,線條的末端和交點都改成圓角,並且設定為虛線。

矩形

以下方法用來繪製矩形。

  • CanvasRenderingContext2D.rect():繪製矩形路徑。
  • CanvasRenderingContext2D.fillRect():填充一個矩形。
  • CanvasRenderingContext2D.strokeRect():繪製矩形邊框。
  • CanvasRenderingContext2D.clearRect():指定矩形區域的畫素都變成透明。

上面四個方法的格式都一樣,都接受四個引數,分別是矩形左上角的橫座標和縱座標、矩形的寬和高。

CanvasRenderingContext2D.rect()方法用於繪製矩形路徑。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.rect(10,10,100,100);
ctx.fill();

上面程式碼繪製一個正方形,左上角座標為(10,10),寬和高都為 100。

CanvasRenderingContext2D.fillRect()用來向一個矩形區域填充顏色。

var canvas = document.getEleme程式設計客棧ntById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.fillStyle = "green";
ctx.fillRect(10,100);

上面程式碼繪製一個綠色的正方形,左上角座標為(10,10),寬和高都為 100。

CanvasRenderingContext2D.strokeRect()用來繪製一個矩形區域的邊框。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.strokeStyle = "green";
ctx.strokeRect(10,100);

上面程式碼繪製一個綠色的空心正方形,左上角座標為(10,10),寬和高都為 100。

CanvasRenderingContext2D.clearRect()用於擦除指定矩形區域的畫素顏色,等同於把早先的繪製效果都去除。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.fillRect(10,100);
ctx.clearRect(15,15,90,90);

上面程式碼先繪製一個 100 x 100 的正方形,然後在它的內部擦除 90 x 90 的區域,等同於形成了一個 5 畫素寬度的邊框。

弧線

以下方法用於繪製弧形。

  • CanvasRenderingContext2D.arc():通過指定圓心和半徑繪製弧形。
  • CanvasRenderingContext2D.arcTo():通過指定兩根切線和半徑繪製弧形。

CanvasRenderingContext2D.arc()主要用來繪製圓形或扇形。

// 格式
ctx.arc(x,y,radius,startAngle,endAngle,anticlockwise);

// 例項
ctx.arc(5,5,2 * Math.PI,true);

arc()方法的x和y引數是圓心座標,radius是半徑,startAngle和endAngle則是扇形的起始角度和終止角度(以弧度表示),anticlockwise表示做圖時應該逆時針畫(true)還是順時針畫(false),這個引數用來控制扇形的方向(比如上半圓還是下半圓)。

下面是繪製實心圓形的例子。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.beginPath();
ctx.arc(60,60,50,Math.PI * 2,true);
ctx.fill();

上面程式碼繪製了一個半徑 50,起始角度為 0,終止角度為 2 * PI 的完整的圓。

繪製空心半圓的例子。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.beginPath();
ctx.moveTo(50,20);
ctx.arc(100,20,Math.PI,false);
ctx.stroke();

CanvasRenderingContext2D.arcTo()方法主要用來繪製圓弧,需要給出兩個點的座標,當前點與第一個點形成一條直線,第一個點與第二個點形成另一條直線,然後畫出與這兩根直線相切的弧線。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.beginPath();
ctx.moveTo(0,0);
ctx.arcTo(50,25);
ctx.lineTo(100,0);
ctx.stroke();

上面程式碼中,arcTo()有 5 個引數,前兩個引數是第一個點的座標,第三個引數和第四個引數是第二個點的座標,第五個引數是半徑。然後,(0,0)與(50,50)形成一條直線,然後(50,50)與(100,0)形成第二條直線。弧線就是與這兩根直線相切的部分。

文字

以下方法和屬性用於繪製文字。

  • CanvasRenderingContext2D.fillText():在指定位置繪製實心字元。
  • CanvasRenderingContext2D.strokeText():在指定位置繪製空心字元。
  • CanvasRenderingContext2D.measureText():返回一個 TextMetrics 物件。
  • CanvasRenderingContext2D.font:指定字型大小和字型,預設值為10px sans-serif。CanvasRenderingContext2D.textAlign:文字的對齊方式,預設值為start。
  • CanvasRenderingContext2D.direction:文字的方向,預設值為inherit。
  • CanvasRenderingContext2D.textBaseline:文字的垂直位置,預設值為alphabetic。

fillText()方法用來在指定位置繪製實心字元。

CanvasRenderingContext2D.fillText(text,x,y [,maxWidth])

該方法接受四個引數。

  • text:所要填充的字串。
  • x:文字起點的橫座標,單位畫素。
  • y:文字起點的縱座標,單位畫素。
  • maxWidth:文字的最大畫素寬度。該引數可選,如果省略,則表示寬度沒有限制。如果文字實際長度超過這個引數指定的值,那麼瀏覽器將嘗試用較小的字型填充。
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.fillText("Hello world",50);

上面程式碼在(50,50)位置寫入字串Hello world。

注意,fillText()方法不支援文字斷行,所有文字一定出現在一行內。如果要生成多行文字,只有呼叫多次fillText()方法。

strokeText()方法用來新增空心字元,它的引數與fillText()一致。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.strokeText("Hello whttp://www.cppcns.comorld",50);

上面這兩種方法繪製的文字,預設都是10px大小、sans-serif字型,font屬性可以改變字型設定。該屬性的值是一個字串,使用css的font屬性即可。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.font = "Bold 20px Arial";
ctx.fillText("Hello world",50);

textAlign屬性用來指定文字的對齊方式。它可以取以下幾個值。

  • left:左對齊
  • right:右對齊
  • center:居中
  • start:預設值,起點對齊(從左到右的文字為左對齊,從右到左的文字為右對齊)。
  • end:結尾對齊(從左到右的文字為右對齊,從右到左的文字為左對齊)。
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.font = "Bold 20px Arial";
ctx.textAlign = "center";
ctx.fillText("Hello world",50);

direction屬性指定文字的方向,預設值為inherit,表示繼承<canvas>或document的設定。其他值包括ltr(從左到右)和rtl(從右到左)。

textBaseline屬性指定文字的垂直位置,可以取以下值。

  • top:上部對齊(字母的基線是整體上移)。
  • hanging:懸掛對齊(字母的上沿在一根直線上),適用於印度文和藏文。
  • middle:中部對齊(字母的中線在一根直線上)。
  • alphabetic:預設值,表示字母位於字母表的正常位置(四線格的第三根線)。
  • ideographic:下沿對齊(字母的下沿在一根直線上),使用於東亞文字。
  • bottom:底部對齊(字母的基線下移)。對於英文字母,這個設定與ideographic沒有差異。

measureText()方法接受一個字串作為引數,返回一個 TextMetrics 物件,可以從這個物件上面獲取引數字串的資訊,目前主要是文字渲染後的寬度(width)。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

var text1 = ctx.measureText("Hello world");
text.width; // 49.46

ctx.font = "Bold 20px Arial";
text2.width; // 107.78

上面程式碼中,10px大小的字串Hello world,渲染後寬度為49.46。放大到20px以後,寬度為107.78。

漸變色和影象填充

以下方法用於設定漸變效果和影象填充效果。

  • CanvasRenderingContext2D.createLinearGradient():定義線性漸變樣式。
  • CanvasRenderingContext2D.createRadialGradient():定義輻射漸變樣式。
  • CanvasRenderingContext2D.createPattern():定義影象填充樣式。

createLinearGradient()方法按照給定直線,生成線性漸變的樣式。

ctx.createLinearGradient(x0,y0,x1,y1);

ctx.createLinearGradient(x0,y1)方法接受四個引數:x0和y0是起點的橫座標和縱座標,x1和y1是終點的橫座標和縱座標。通過不同的座標值,可以生成從上至下、從左到右的漸變等等。

該方法的返回值是一個CanvasGradient物件,該物件只有一個addColorStop()方向,用來指定漸變點的顏色。addColorStop()方法接受兩個引數,第一個引數是 0 到 1 之間的一個位置量,0 表示起點,1 表示終點,第二個引數是一個字串,表示css顏色。

var canvas = docu程式設計客棧ment.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

var gradient = ctx.createLinearGradient(0,200,0);
gradient.addColorStop(0,"green");
gradient.addColorStop(1,"white");
ctx.fillStyle = gradient;
ctx.fillRect(10,100);

上面程式碼中,定義了漸變樣式gradient以後,將這個樣式指定給fillStyle屬性,然後fillRect()就會生成以這個樣式填充的矩形區域。

createRadialGradient()方法定義一個輻射漸變,需要指定兩個圓。

ctx.createRadialGradient(x0,r0,y1,r1);

createRadialGradient()方法接受六個引數,x0和y0是輻射起始的圓的圓心座標,r0是起始圓的半徑,x1和y1是輻射終止的圓的圓心座標,r1是終止圓的半徑。

該方法的返回值也是一個CanvasGradient物件。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

var gradient = ctx.createRadialGradient(100,100);
gradient.addColorStop(0,"white");
gradient.addColorStop(1,"green");
ctx.fillStyle = gradient;
ctx.fillRect(0,200);

上面程式碼中,生成輻射樣式以後,用這個樣式填充一個矩形。

createPattern()方法定義一個影象填充樣式,在指定方向上不斷重複該影象,填充指定的區域。

ctx.createPattern(image,repetition);

該方法接受兩個引數,第一個引數是影象資料,它可以是<img>元素,也可以是另一個<canvas>元素,或者一個表示影象的 Blob 物件。第二個引數是一個字串,有四個可能的值,分別是repeat(雙向重複)、repeat-x(水平重複)、repeat-y(垂直重複)、no-repeat(不重複)。如果第二個引數是空字串或null,則等同於null。

該方法的返回值是一個CanvasPattern物件。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

var img = new Image();
img.src = "https://example.com/pattern.png";
img.onload = function() {
  var pattern = ctx.createPattern(img,"repeat");
  ctx.fillStyle = pattern;
  ctx.fillRect(0,400,400);
};

上面程式碼中,影象載入成功以後,使用createPattern()生成影象樣式,然後使用這個樣式填充指定區域。

陰影

以下屬性用於設定陰影。

  • CanvasRenderingContext2D.shadowBlur:陰影的模糊程度,預設為0。
  • CanvasRenderingContext2D.shadowColor:陰影的顏色,預設為black。
  • CanvasRenderingContext2D.shadowOffsetX:陰影的水平位移,預設為0。
  • CanvasRenderingContext2D.shadowOffsetY:陰影的垂直位移,預設為0。

下面是一個例子。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.shadowOffsetX = 10;
ctx.shadowOffsetY = 10;
ctx.shadowBlur = 5;
ctx.shadowColor = "rgba(0,0.5)";

ctx.fillStyle = "green";
ctx.fillRect(10,100);

Canvas API:影象處理

CanvasRenderingContext2D.drawImage()

Canvas API 允許將影象檔案寫入畫布,做法是讀取圖片後,使用drawImage()方法將這張圖片放上畫布。

CanvasRenderingContext2D.drawImage()有三種使用格式。

ctx.drawImage(image,dx,dy);
ctx.drawImage(image,dy,dWidth,dHeight);
ctx.drawImage(image,sx,sy,sWidth,sHeight,dHeight);

各個引數的含義如下。

  • image:影象元素
  • sx:影象內部的橫座標,用於對映到畫布的放置點上。
  • sy:影象內部的縱座標,用於對映到畫布的放置點上。
  • sWidth:影象在畫布上的寬度,會產生縮放效果。如果未指定,則影象不會縮放,按照實際大小佔據畫布的寬度。
  • sHeight:影象在畫布上的高度,會產生縮放效果。如果未指定,則影象不會縮放,按照實際大小佔據畫布的高度。
  • dx:畫布內部的橫座標,用於放置影象的左上角
  • dy:畫布內部的縱座標,用於放置影象的右上角
  • dWidth:影象在畫布內部的寬度,會產生縮放效果。
  • dHeight:影象在畫布內部的高度,會產生縮放效果。

下面是最簡單的使用場景,將影象放在畫布上,兩者左上角對齊。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

var img = new Image();
img.src = "image.png";
img.onload = function() {
  ctx.drawImage(img,0);
};

上面程式碼將一個 PNG 影象放入畫布。這時,影象將是原始大小,如果畫布小於影象,就會只顯示出影象左上角,正好等於畫布大小的那一塊。

如果要顯示完整的圖片,可以用影象的寬和高,設定成畫布的寬和高。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

var image = new Image(60,45);
image.onload = drawImageActualSize;
image.src = "https://example.com/image.jpg";

function drawImageActualSize() {
  canvas.width = this.naturalWidth;
  canvas.height = this.naturalHeight;
  ctx.drawImage(this,this.naturalWidth,this.naturalHeight);
}

上面程式碼中,<canvas>元素的大小設定成影象的本來大小,就能保證完整展示影象。由於影象的本來大小,只有影象載入成功以後才能拿到,因此調整畫布的大小,必須放在image.onload這個監聽函式裡面。

畫素讀寫

以下三個方法與畫素讀寫相關。

  • CanvasRenderingContext2D.getImageData():將畫布讀取成一個 ImageData 物件
  • CanvasRenderingContext2D.putImageData():將 ImageData 物件寫入畫布
  • CanvasRenderingContext2D.createImageData():生成 ImageData 物件

(1)getImageData()

CanvasRenderingContext2D.getImageData()方法用來讀取<canvas>的內容,返回一個 ImageData 物件,包含了每個畫素的資訊。

ctx.getImageData(sx,sw,sh);

getImageData()方法接受四個引數。sx和sy是讀取區域的左上角座標,sw和sh是讀取區域的寬度和高度。如果想要讀取整個<canvas>區域,可以寫成下面這樣。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

var imageData = ctx.getImageData(0,canvas.width,canvas.height);

getImageData()方法返回的是一個ImageData物件。該物件有三個屬性。

  • ImageData.data:一個一維陣列。該陣列的值,依次是每個畫素的紅、綠、藍、alpha 通道值(每個值的範圍是 0 ~ 255),因此該陣列的長度等於影象的畫素寬度 x 影象的畫素高度 x 4。這個陣列不僅可讀,而且可寫,因此通過操作這個陣列,就可以達到操作影象的目的。
  • ImageData.width:浮點數,表示 ImageData 的畫素寬度。
  • ImageData.height:浮點數,表示 ImageData 的畫素高度。

(2)putImageData()

CanvasRenderingContext2D.putImageData()方法將ImageData物件的畫素繪製在<canvas>畫布上。該方法有兩種使用格式。

ctx.putImageData(imagedata,dy);
ctx.putImageData(imagedata,dirtyX,dirtyY,dirtyWidth,dirtywww.cppcns.comHeight);

該方法有如下引數。

  • imagedata:包含畫素資訊的 ImageData 物件。
  • dx:<canvas>元素內部的橫座標,用於放置 ImageData 影象的左上角。
  • dy:<canvas>元素內部的縱座標,用於放置 ImageData 影象的左上角。
  • dirtyX:ImageData 影象內部的橫座標,用於作為放置到<canvas>的矩形區域的左上角的橫座標,預設為 0。
  • dirtyY:ImageData 影象內部的縱座標,用於作為放置到<canvas>的矩形區域的左上角的縱座標,預設為 0。
  • dirtyWidth:放置到<canvas>的矩形區域的寬度,預設為 ImageData 影象的寬度。
  • dirtyHeight:放置到<canvas>的矩形區域的高度,預設為 ImageData 影象的高度。

下面是將 ImageData 物件繪製到<canvas>的例子。

ctx.putImageData(imageData,0);

(3)createImageData()

CanvasRenderingContext2D.createImageData()方法用於生成一個空的ImageData物件,所有畫素都是透明的黑色(即每個值都是0)。該方法有兩種使用格式。

ctx.createImageData(width,height);
ctx.createImageData(imagedata);

createImageData()方法的引數如下。

  • width:ImageData 物件的寬度,單位為畫素。
  • height:ImageData 物件的高度,單位為畫素。
  • imagedata:一個現有的 ImageData 物件,返回值將是這個物件的拷貝。
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

var imageData = ctx.createImageData(100,100);

上面程式碼中,imageData是一個 100 x 100 的畫素區域,其中每個畫素都是透明的黑色。

CanvasRenderingContext2D.save(),CanvasRenderingContext2D.restore()

CanvasRenderingContext2D.save()方法用於將畫布的當前樣式儲存到堆疊,相當於在記憶體之中產生一個樣式快照。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.save();

上面程式碼中,save()會為畫布的預設樣式產生一個快照。

CanvasRenderingContext2D.restore()方法將畫布的樣式恢復到上一個儲存的快照,如果沒有已儲存的快照,則不產生任何效果。

上下文環境,restore 方法用於恢復到上一次儲存的上下文環境。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.save();

ctx.fillStyle = "green";
ctx.restore();

ctx.fillRect(10,100);

上面程式碼畫一個矩形。矩形的填充色本來設為綠色,但是restore()方法撤銷了這個設定,將樣式恢復上一次儲存的狀態(即預設樣式),所以實際的填充色是黑色(預設顏色)。

CanvasRenderingContext2D.canvas

CanvasRenderingContext2D.canvas屬性指向當前CanvasRenderingContext2D物件所在的<canvas>元素。該屬性只讀。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.canvas === canvas; // true

影象變換

以下方法用於影象變換。

  • CanvasRenderingContext2D.rotate():影象旋轉
  • CanvasRenderingContext2D.scale():影象縮放
  • CanvasRenderingContext2D.translate():影象平移
  • CanvasRenderingContext2D.transform():通過一個變換矩陣完成影象變換
  • CanvasRenderingContext2D.setTransform():取消前面的影象變換

(1)rotate()

CanvasRenderingContext2D.rotate()方法用於影象旋轉。它接受一個弧度值作為引數,表示順時針旋轉的度數。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.rotate((45 * Math.PI) / 180);
ctx.fillRect(70,30);

上面程式碼會顯示一個順時針傾斜 45 度的矩形。注意,rotate()方法必須在fillRect()方法之前呼叫,否則是不起作用的。

旋轉中心點始終是畫布左上角的原點。如果要更改中心點,需要使用translate()方法移動畫布。

(2)scale()

CanvasRenderingContext2D.scale()方法用於縮放影象。它接受兩個引數,分別是x軸方向的縮放因子和y軸方向的縮放因子。預設情況下,一個單位就是一個畫素,縮放因子可以縮放單位,比如縮放因子0.5表示將大小縮小為原來的 50%,縮放因子10表示放大十倍。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.scale(10,3);
ctx.fillRect(10,10);

上面程式碼中,原來的矩形是 10 x 10,縮放後展示出來是 100 x 30。

如果縮放因子為 1,就表示影象沒有任何縮放。如果為-1,則表示方向翻轉。ctx.scale(-1,1)為水平翻轉,ctx.scale(1,-1)表示垂直翻轉。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.scale(1,-2);
ctx.font = "16px serif";
ctx.fillText("Hello world!",-20);

上面程式碼會顯示一個水平倒轉的、高度放大 2 倍的Hello World!。

注意,負向縮放本質是座標翻轉,所針對的座標軸就是畫布左上角原點的座標軸。

(3)translate()

CanvasRenderingContext2D.translate()方法用於平移影象。它接受兩個引數,分別是 x 軸和 y 軸移動的距離(單位畫素)。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.translate(50,50);
ctx.fillRect(0,100);

(4)transform()

CanvasRenderingContext2D.transform()方法接受一個變換矩陣的六個元素作為引數,完成縮放、旋轉、移動和傾斜等變形。

它的使用格式如下。

ctx.transform(a,b,c,d,e,f);
/*
a:水平縮放(預設值1,單位倍數)
b:水平傾斜(預設值0,單位弧度)
c:垂直傾斜(預設值0,單位弧度)
d:垂直縮放(預設值1,單位倍數)
e:水平位移(預設值0,單位畫素)
f:垂直位移(預設值0,單位畫素)
*/

下面是一個例子。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.transform(2,1,100);

上面程式碼中,原始圖形是 100 x 100 的矩形,結果縮放成 200 x 100 的矩形,並且左上角從(0,0)移動到(50,50)。

注意,多個transform()方法具有疊加效果。

(5)setTransform()

CanvasRenderingContext2D.setTransform()方法取消前面的圖形變換,將畫布恢復到該方法指定的狀態。該方法的引數與transform()方法完全一致。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

ctx.translate(50,100);

ctx.setTransform(1,0);
ctx.fillRect(0,100);

上面程式碼中,第一個fillRect()方法繪製的矩形,左上角從(0,0)平移到(50,50)。setTransform()方法取消了這個變換(已繪製的圖形不受影響),將畫布恢復到預設狀態(變換矩形1,0),所以第二個矩形的左上角回到(0,0)。

canvas元素的方法

除了CanvasRenderingContext2D物件提供的方法,<canvas>元素本身也有自己的方法。

htmlCanvasElement.toDataURL()

<canvas>元素的toDataURL()方法,可以將 Canvas資料轉為 Data URI 格式的影象。

canvas.toDataURL(type,quality);

toDataURL()方法接受兩個引數。

  • type:字串,表示影象的格式。預設為image/png,另一個可用的值是image/jpeg,Chrome 瀏覽器還可以使用image/webp。
  • quality:浮點數,0 到 1 之間,表示 JPEG 和 WebP 影象的質量係數,預設值為 0.92。

該方法的返回值是一個 Data URI 格式的字串。

function convertCanvasToImage(canvas) {
  var image = new Image();
  image.src = canvas.toDataURL("image/png");
  return image;
}

上面的程式碼將<canvas>元素,轉化成 PNG Data URI。

var fullQuality = canvas.toDataURL("image/jpeg",0.9);
var mediumQuality = canvas.toDataURL("image/jpeg",0.6);
var lowQuality = canvas.toDataURL("image/jpeg",0.3);

上面程式碼將<canvas>元素轉成高畫質、中畫質、低畫質三種 JPEG 影象。

htmlCanvasElement.toBlob()

HTMLCanvasElement.toBlob()方法用於將<canvas>影象轉成一個 Blob 物件,預設型別是image/png。它的使用格式如下。

// 格式
canvas.toBlob(callback,mimeType,quality)

// 示例
canvas.toBlob(function (blob) {...},'image/jpeg',0.95)

toBlob()方法可以接受三個引數。

  • callback:回撥函式。它接受生成的 Blob 物件作為引數。
  • dZYLC
  • mimeType:字串,影象的 MIMEType 型別,預設是image/png。
  • quality:浮點數,0 到 1 之間,表示影象的質量,只對image/jpeg和image/webp型別的影象有效。

注意,該方法沒有返回值。

下面的例子將<canvas>影象複製成<img>影象。

var canvas = document.getElementById('myCanvas');

function blobToImg(blob) {
  var newImg = document.createElement('img');
  var url = URL.createObjectURL(blob);

  newImg.onload = functio () {
    // 使用完畢,釋放 URL 物件
    URL.revokeObjectURL(url);
  };

  newImg.src = url;
  document.body.appendChild(newImg);
}

canvas.toBlob(blobToImg);

Canvas 使用例項

動畫效果

通過改變座標,很容易在畫布 Canvas 元素上產生動畫效果。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

var posX = 20;
var posY = 100;

setInterval(function() {
  ctx.fillStyle = "black";
  ctx.fillRect(0,canvas.height);

  posX += 1;
  posY += 0.25;

  ctx.beginPath();
  ctx.fillStyle = "white";

  ctx.arc(posX,posY,true);
  ctx.closePath();
  ctx.fill();
},30);

上面程式碼會產生一個小圓點,每隔 30 毫秒就向右下方移動的效果。setInterval()函式的一開始,之所以要將畫布重新渲染黑色底色,是為了抹去上一步的小圓點。

在這個例子的基礎上,通過設定圓心座標,可以產生各種運動軌跡。下面是先上升後下降的例子。

var vx = 10;
var vy = -10;
var gravity = 1;

setInterval(function() {
  posX += vx;
  posY += vy;
  vy += gravity;
  // ...
});

上面程式碼中,x座標始終增大,表示持續向右運動。y座標先變小,然後在重力作用下,不斷增大,表示先上升後下降。

畫素處理

通過getImageData()方法和putImageData()方法,可以處理每個畫素,進而操作影象內容,因此可以改寫影象。

下面是影象處理的通用寫法。

if (canvas.width > 0 && canvas.height > 0) {
  var imageData = context.getImageData(0,canvas.height);
  filter(imageData);
  context.putImageData(imageData,0);
}

上面程式碼中,filter是一個處理畫素的函式。以下是幾種常見的filter。

(1)灰度效果

灰度圖(grayscale)就是取紅、綠、藍三個畫素值的算術平均值,這實際上將影象轉成了黑白形式。

grayscale = function(pixels) {
  var d = pixels.data;
  for (var i = 0; i < d.length; i += 4) {
    var r = d[i];
    var g = d[i + 1];
    var b = d[i + 2];
    d[i] = d[i + 1] = d[i + 2] = (r + g + b) / 3;
  }
  return pixels;
};

上面程式碼中,d[i]是紅色值,d[i+1]是綠色值,d[i+2]是藍色值,d[i+3]是 alpha 通道值。轉成灰度的演算法,就是將紅、綠、藍三個值相加後除以 3,再將結果寫回陣列。

(2)復古效果

復古效果(sepia)是將紅、綠、藍三種值,分別取這三個值的某種加權平均值,使得影象有一種古舊的效果。

sepia = function(pixels) {
  var d = pixels.data;
  for (var i = 0; i < d.length; i += 4) {
    var r = d[i];
    var g = d[i + 1];
    var b = d[i + 2];
    d[i] = r * 0.393 + g * 0.769 + b * 0.189; // red
    d[i + 1] = r * 0.349 + g * 0.686 + b * 0.168; // green
    d[i + 2] = r * 0.272 + g * 0.534 + b * 0.131; // blue
  }
  return pixels;
};

(3)紅色蒙版效果

紅色蒙版指的是,讓影象呈現一種偏紅的效果。演算法是將紅色通道設為紅、綠、藍三個值的平均值,而將綠色通道和藍色通道都設為 0。

var red = function(pixels) {
  var d = pixels.data;
  for (var i = 0; i < d.length; i += 4) {
    var r = d[i];
    var g = d[i + 1];
    var b = d[i + 2];
    d[i] = (r + g + b) / 3; // 紅色通道取平均值
    d[i + 1] = d[i + 2] = 0; // 綠色通道和藍色通道都設為0
  }
  return pixels;
};

(4)亮度效果

亮度效果(brightness)是指讓影象變得更亮或更暗。演算法將紅色通道、綠色通道、藍色通道,同時加上一個正值或負值。

var brightness = function(pixels,delta) {
  var d = pixels.data;
  for (var i = 0; i < d.length; i += 4) {
    d[i] += delta; // red
    d[i + 1] += delta; // green
    d[i + 2] += delta; // blue
  }
  return pixels;
};

(5)反轉效果

反轉效果(invert)是指圖片呈現一種色彩顛倒的效果。演算法為紅、綠、藍通道都取各自的相反值(255 - 原值)。

invert = function(pixels) {
  var d = pixels.data;
  for (var i = 0; i < d.length; i += 4) {
    d[i] = 255 - d[i];
    d[i + 1] = 255 - d[i + 1];
    d[i + 2] = 255 - d[i + 2];
  }
  return pixels;
};

以上就是js Canvas介面和動畫效果大全的詳細內容,更多關於JS的資料請關注我們其它相關文章!