Canvas詳解

<canvas>標(biāo)簽用于繪制圖像(通過腳本,通常是 JavaScript)。不過,<canvas>元素本身并沒有繪制能力(它僅僅是圖形的容器) - 您必須使用腳本來完成實(shí)際的繪圖任務(wù)。

Internet Explorer 9、Firefox2.0、Opera9.0、Chrome4.0 以及 Safari3.1 支持 <canvas> 及其屬性和方法。


開始使用

  • 首先新建一個(gè)<canvas>網(wǎng)頁元素。
<canvas id="myCanvas" width="400" height="200">
你的瀏覽器不支持canvas!
</canvas>

上面代碼中,如果瀏覽器不支持,則就會(huì)顯示<canvas>標(biāo)簽中間的文字——“您de瀏覽器不支持canvas!”。

  • 取這個(gè)canvas對(duì)象,方法是使用getContext。
var canvas = document.getElementById('myCanvas');

if (canvas.getContext) {
  var ctx = canvas.getContext('2d');
}

getContext方法指定參數(shù)2d,表示該canvas節(jié)點(diǎn)用于生成2D圖案(即平面圖案)。如果參數(shù)是webgl,就表示用于生成3D圖像(即立體圖案),這部分實(shí)際上單獨(dú)叫做WebGL API。


繪圖方法

canvas畫布提供了一個(gè)用來作圖的平面空間,該空間的每個(gè)點(diǎn)都有自己的坐標(biāo),x表示橫坐標(biāo),y表示豎坐標(biāo)。原點(diǎn)(0, 0)位于圖像左上角,x軸的正向是原點(diǎn)向右,y軸的正向是原點(diǎn)向下

繪制路徑

beginPath方法表示開始繪制路徑,
moveTo(x, y)方法設(shè)置線段的起點(diǎn),
lineTo(x, y)方法設(shè)置線段的終點(diǎn),
stroke方法用來給透明的線段著色。

ctx.beginPath(); // 開始路徑繪制
ctx.moveTo(20, 20); // 設(shè)置路徑起點(diǎn),坐標(biāo)為(20,20)
ctx.lineTo(200, 20); // 繪制一條到(200,20)的直線
ctx.lineWidth = 1.0; // 設(shè)置線寬
ctx.strokeStyle = '#CC0000'; // 設(shè)置線的顏色
ctx.stroke(); // 進(jìn)行線的著色,這時(shí)整條線才變得可見
繪制直線

movetolineto方法可以多次使用。最后,還可以使用closePath方法,自動(dòng)繪制一條當(dāng)前點(diǎn)到起點(diǎn)的直線,形成一個(gè)封閉圖形,省卻使用一次lineto方法。

ctx.beginPath();
ctx.moveTo(40,20);
ctx.lineTo(60,20);
ctx.lineTo(60,40);
ctx.lineTo(40,40);
ctx.lineTo(40,20);//繪制閉合圖形時(shí),可以替換成ctx.closePath();
ctx.lineWidth = 1.0;
ctx.strokeStyle = '#CC0000';
ctx.stroke();
閉合圖形
繪制矩形

fillRect(x, y, width, height)方法用來繪制矩形,它的四個(gè)參數(shù)分別為矩形左上角頂點(diǎn)的x坐標(biāo)、y坐標(biāo),以及矩形的寬和高。fillStyle屬性用來設(shè)置矩形的填充色。

ctx.fillStyle = 'yellow';
ctx.fillRect(50, 50, 200, 100); 
實(shí)心閉合矩形

strokeRect(x, y, width, height)方法與fillRect類似,用來繪制空心矩形。

ctx.strokeRect(60,200,200,100);
空心閉合矩形

clearRect(x, y, width, height)方法用來清除某個(gè)矩形區(qū)域的內(nèi)容。

ctx.clearRect(100,50,50,50); 
被清除的矩形塊
繪制文本

fillText(string, x, y)用來繪制文本,它的三個(gè)參數(shù)分別為文本內(nèi)容、起點(diǎn)的x坐標(biāo)、y坐標(biāo)。使用之前,需用font設(shè)置字體、大小、樣式(寫法類似與CSS的font屬性)。與此類似的還有strokeText(string, x, y)方法,用來添加空心字。

ctx.font = "Bold 20px Arial";// 設(shè)置字體
ctx.textAlign = "left";// 設(shè)置對(duì)齊方式
ctx.fillStyle = "#333";// 設(shè)置填充顏色
ctx.fillText("Hello!", 320, 50);// 設(shè)置字體內(nèi)容,以及在畫布上的位置
ctx.textAlign = "center";// 設(shè)置對(duì)齊方式
ctx.strokeStyle = "#000";// 設(shè)置顏色
ctx.strokeText("Hello!",320, 80);// 繪制空心字
ctx.textAlign = "right";// 設(shè)置對(duì)齊方式
ctx.strokeStyle = "green";// 設(shè)置顏色
ctx.strokeText("Hello!",320, 110);// 繪制空心字

繪制文本

注意

  • 當(dāng)繪制空心字時(shí),著色應(yīng)使用strokeStyle;而繪制實(shí)心字時(shí),使用fillStyle來著色
  • textAlign方法與我們css中所理解的有所區(qū)別,舉個(gè)栗子你就明白啦
// 在位置 600 創(chuàng)建藍(lán)線
ctx.strokeStyle="blue";
ctx.moveTo(600,20);
ctx.lineTo(600,170);
ctx.stroke();

ctx.font="15px Arial";

// 顯示不同的 textAlign 值
ctx.textAlign="start";
ctx.fillText("textAlign=start",600,60);
ctx.textAlign="end";
ctx.fillText("textAlign=end",600,80);
ctx.textAlign="left";
ctx.fillText("textAlign=left",600,100);
ctx.textAlign="center";
ctx.fillText("textAlign=center",600,120);
ctx.textAlign="right";
ctx.fillText("textAlign=right",600,140);
textAlign栗子

fillText方法不支持文本斷行,即所有文本出現(xiàn)在一行內(nèi)。所以,如果要生成多行文本,只有調(diào)用多次fillText方法。
家庭作業(yè):使用canvas繪制多行文本

繪制圓形和扇形

arc(x, y, radius, startAngle, endAngle, anticlockwise)方法用來繪制扇形,xy參數(shù)是圓心坐標(biāo),radius是半徑,startAngleendAngle則是扇形的起始角度和終止角度(以弧度表示),anticlockwise表示做圖時(shí)應(yīng)該逆時(shí)針畫true,還是順時(shí)針畫false。

//繪制實(shí)心圓
ctx.beginPath(); 
ctx.arc(60, 60, 50, 0, Math.PI*2, true); 
ctx.fillStyle = "#000000"; 
ctx.fill();

//繪制空心圓形
ctx.beginPath(); 
ctx.arc(60, 60, 50, 0, Math.PI*2, true); 
ctx.lineWidth = 1.0; 
ctx.strokeStyle = "#000"; 
ctx.stroke();
for(var i = 0; i < 10;i++){
  context.beginPath();
  context.arc(50 + i*100,60,40,0,2*Math.PI*(i+1)/10);
  context.closePath();//沒有閉合的圓弧,會(huì)自動(dòng)閉合圖形
  context.stroke();
}

for (var i = 0; i < 10; i++) {
  context.beginPath();
  context.arc(50 + i * 100, 180, 40, 0, 2 * Math.PI * (i + 1) / 10);
  context.stroke();
}

for (var i = 0; i < 10; i++) {
  context.beginPath();
  context.arc(50 + i * 100, 300, 40, 0, 2*Math.PI * (i + 1)/10 , true);
  context.closePath();
  context.stroke();
}

for (var i = 0; i < 10; i++) {
  context.beginPath();
  context.arc(50 + i * 100, 420, 40, 0, 2 * Math.PI * (i + 1) / 10, true);
  context.stroke();
}

context.fillStyle = '#058';
for (var i = 0; i < 10; i++) {
  context.beginPath();
  context.arc(50 + i * 100, 540, 40, 0, 2 * Math.PI * (i + 1) / 10);
  context.closePath();//有無closePath對(duì)于fill填充無效
  context.fill();
}

for (var i = 0; i < 10; i++) {
  context.beginPath();
  context.arc(50 + i * 100, 660, 40, 0, 2 * Math.PI * (i + 1) / 10);
  context.fill();
}

圓弧詳解

注意

  • anticlockwise參數(shù)省略時(shí),默認(rèn)為順時(shí)針;
  • closePath()在繪制空心圓弧時(shí),依然會(huì)自動(dòng)閉合圖??;對(duì)實(shí)心圓弧則無效
設(shè)置漸變色

createLinearGradient(x1, y1, x2, y2)用來設(shè)置漸變色,其中x1和y1是起點(diǎn)坐標(biāo),x2和y2是終點(diǎn)坐標(biāo)。通過不同的坐標(biāo)值,可以生成從上至下、從左到右的漸變等等。使用該對(duì)象作為 strokeStylefillStyle 屬性的值,可用于填充矩形、圓形、線條、文本等等。使用 addColorStop()方法規(guī)定不同的顏色,以及在 gradient 對(duì)象中的何處定位顏色

var my_gradient=ctx.createLinearGradient(500,0,700,0);
my_gradient.addColorStop(0,"black");
my_gradient.addColorStop(0.5,"red");
my_gradient.addColorStop(1,"white");
ctx.fillStyle=my_gradient;
ctx.strokeStyle = my_gradient;
ctx.fillRect(500,300,200,100);//繪制漸變圖形
ctx.moveTo(500,430);
ctx.lineTo(700,430);
ctx.stroke();//繪制漸變線
ctx.textAlign="left";
ctx.fillText("Hello!Hello!Hello!Hello!Hello!Hello!Hello!Hello!", 500, 470);//繪制漸變字
線性漸變

createLinearGradient(x0,y0,r0,x1,y1,r1) 方法創(chuàng)建放射狀/圓形漸變對(duì)象,x0漸變的開始圓的 x 坐標(biāo);y0漸變的開始圓的 y 坐標(biāo); r0開始圓的半徑;x1漸變的結(jié)束圓的 x 坐標(biāo);y1漸變的結(jié)束圓的 y 坐標(biāo);r1結(jié)束圓的半徑

var radialGrad = context.createRadialGradient(400,400,0,400,400,500);
radialGrad.addColorStop(0.0,'white');
radialGrad.addColorStop(0.25,'yellow');
radialGrad.add.ColorStop(0.5,'green');
radialGrad.add.ColorStop(0.75,'blue');
radialGrad.add.ColorStop(1.0,'black');

context.fillStyle = radialGrad;
context.fillRect(0,0,800,800);
圓形漸變
設(shè)置陰影

shadowBlur方法設(shè)置陰影的模糊范圍;
shadowOffsetX方法設(shè)置水平位移;
shadowOffsetY方法設(shè)置垂直位移;
shadowColor設(shè)置陰影顏色

ctx.shadowOffsetX = 10; // 設(shè)置水平位移
ctx.shadowOffsetY = 10; // 設(shè)置垂直位移
ctx.shadowBlur = 5; // 設(shè)置模糊度
ctx.shadowColor = "rgba(0,0,0,0.5)"; // 設(shè)置陰影顏色

ctx.fillStyle = "#CC0000"; 
ctx.fillRect(10,10,200,100);
陰影

圖像處理方法

drawImage方法

Canvas允許將圖像文件插入畫布,做法是讀取圖片后,使用drawImage方法在畫布內(nèi)進(jìn)行重繪。
drawImage(img,sx,sy,swidth,sheight,x,y,width,height)
img 規(guī)定要使用的圖像、畫布或視頻。
sx 可選。開始剪切的 x 坐標(biāo)位置。
sy 可選。開始剪切的 y 坐標(biāo)位置。
swidth 可選。被剪切圖像的寬度。
sheight 可選。被剪切圖像的高度。
x 在畫布上放置圖像的 x 坐標(biāo)位置。
y 在畫布上放置圖像的 y 坐標(biāo)位置。
width 可選。要使用的圖像的寬度。(伸展或縮小圖像)
height 可選。要使用的圖像的高度。(伸展或縮小圖像)

var img = new Image();
img.src = 'image.png';
ctx.drawImage(img, 0, 0); // 設(shè)置對(duì)應(yīng)的圖像對(duì)象,以及它在畫布上的位置

上面代碼將一個(gè)PNG圖像載入畫布。drawImage()方法接受三個(gè)參數(shù),第一個(gè)參數(shù)是圖像文件的DOM元素(即<img>節(jié)點(diǎn)),第二個(gè)和第三個(gè)參數(shù)是圖像左上角在畫布中的坐標(biāo),上例中的(0, 0)就表示將圖像左上角放置在畫布的左上角。

由于圖像的載入需要時(shí)間,drawImage方法只能在圖像完全載入后才能調(diào)用,因此上面的代碼并沒有成功畫入圖片,需要改寫:

var image = new Image();
image.onload = function() {
  var canvas = document.createElement('canvas');
  canvas.width = image.width;
  canvas.height = image.height;
  canvas.getContext('2d').drawImage(image, 0, 0);
  // 插入頁面底部
  document.body.appendChild(image);
  return canvas;
}

image.src = 'image.jpg';

new Image()
new Image()用途

getImageData方法,putImageData方法

通過 getImageData(x,y,width,height)復(fù)制畫布上指定矩形的像素?cái)?shù)據(jù),
然后通過 putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight) 將圖像數(shù)據(jù)放回畫布。

getImageData(x,y,width,height)
x 開始復(fù)制的左上角位置的 x 坐標(biāo)(以像素計(jì))。
y 開始復(fù)制的左上角位置的 y 坐標(biāo)(以像素計(jì))
width 要復(fù)制的矩形區(qū)域的寬度。
height 要復(fù)制的矩形區(qū)域的高度。
getImageData() 方法返回 ImageData 對(duì)象,該對(duì)象拷貝了畫布指定矩形的像素?cái)?shù)據(jù)。

注意:ImageData 對(duì)象不是圖像,它規(guī)定了畫布上一個(gè)部分(矩形),并保存了該矩形內(nèi)每個(gè)像素的信息。
對(duì)于 ImageData 對(duì)象中的每個(gè)像素,都存在著四方面的信息,即 RGBA 值:

  • R - 紅色(0-255)
  • G - 綠色(0-255)
  • B - 藍(lán)色(0-255)
  • A - alpha 通道(0-255; 0 是透明的,255 是完全可見的)

color/alpha 信息以數(shù)組形式存在,并存儲(chǔ)于 ImageData 對(duì)象的 data 屬性中。

putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight)
imgData 規(guī)定要放回畫布的 ImageData 對(duì)象。
x ImageData 對(duì)象左上角的 x 坐標(biāo),以像素計(jì)。
y ImageData 對(duì)象左上角的 y 坐標(biāo),以像素計(jì)。
dirtyX 可選。水平值(x),以像素計(jì),在畫布上放置圖像的位置。
dirtyY 可選。垂直值(y),以像素計(jì),在畫布上放置圖像的位置。
dirtyWidth 可選。在畫布上繪制圖像所使用的寬度。
dirtyHeight 可選。在畫布上繪制圖像所使用的高度。

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle="red";
ctx.fillRect(10,10,50,50);
function copy()
{
    var imgData=ctx.getImageData(10,10,50,50);
    ctx.putImageData(imgData,10,70);
}
</script>
<button onclick="copy()">復(fù)制</button>
toDataURL方法

對(duì)圖像數(shù)據(jù)做出修改以后,可以使用toDataURL方法,將Canvas數(shù)據(jù)重新轉(zhuǎn)化成一般的圖像文件形式。該方法返回一個(gè)包含圖片展示的 data URI ??梢允褂?type參數(shù)其類型,默認(rèn)為 PNG 格式。圖片的分辨率為96dpi。

toDataURL(type, encoderOptions)
type 可選,圖片格式,默認(rèn)為 image/png
encoderOptions 可選,在指定圖片格式為 image/jpeg 或 image/webp的情況下,可以從 0 到 1 的區(qū)間內(nèi)選擇圖片的質(zhì)量。如果超出取值范圍,將會(huì)使用默認(rèn)值 0.92。其他參數(shù)會(huì)被忽略。

var canvas = document.getElementById("canvas");
var dataURL = canvas.toDataURL();
console.log(dataURL);
// "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAADElEQVQImWNgoBMAAABpAAFEI8ARAAAAAElFTkSuQmCC"
var fullQuality = canvas.toDataURL("image/jpeg", 1.0);
//data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...9oADAMBAAIRAxEAPwD/AD/6AP/Z"
var mediumQuality = canvas.toDataURL("image/jpeg", 0.5);
var lowQuality = canvas.toDataURL("image/jpeg", 0.1);
save方法,restore方法

save:用來保存Canvas的狀態(tài)。save之后,可以調(diào)用Canvas的平移、放縮、旋轉(zhuǎn)、錯(cuò)切、裁剪等操作。 restore:用來恢復(fù)Canvas之前保存的狀態(tài)。防止save后對(duì)Canvas執(zhí)行的操作對(duì)后續(xù)的繪制有影響。

ctx.save();

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

ctx.fillStyle = '#CC0000';
ctx.fillRect(10,10,150,100);

ctx.restore();

ctx.fillStyle = '#000000';
ctx.fillRect(180,10,150,100);

上面代碼先用save方法,保存了當(dāng)前設(shè)置,然后繪制了一個(gè)有陰影的矩形。接著,使用restore方法,恢復(fù)了保存前的設(shè)置,繪制了一個(gè)沒有陰影的矩形。
注意

  • restore只能撤回到上一個(gè)save()的狀態(tài);
  • restore可以多次執(zhí)行,一直向上這回。

https://juejin.im/post/5ac437b5f265da238f12c1c6

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Canvas canvas 最早由Apple引入WebKit,用于Mac OS X 的 Dashboard,后來又...
    zhangjingbibibi閱讀 1,497評(píng)論 0 0
  • ??HTML5 添加的最受歡迎的功能就是 元素。這個(gè)元素負(fù)責(zé)在頁面中設(shè)定一個(gè)區(qū)域,然后就可以通過 JavaScri...
    霜天曉閱讀 3,177評(píng)論 0 2
  • canvas元素的基礎(chǔ)知識(shí) 在頁面上放置一個(gè)canvas元素,就相當(dāng)于在頁面上放置了一塊畫布,可以在其中進(jìn)行圖形的...
    oWSQo閱讀 10,433評(píng)論 0 19
  • 一、簡(jiǎn)介 HTML5 中的定義:“它是依賴分辨率的位圖畫布,你可以在 canvas 上面繪制任何圖形,甚至加載照片...
    destiny0904閱讀 10,818評(píng)論 1 4
  • 1.Canvas Canvas 是我們繪制各種圖形或文字時(shí)主要的操作對(duì)象,因?yàn)槔L制繪制過程調(diào)用的都是它的 draw...
    Kip_Salens閱讀 1,552評(píng)論 0 4

友情鏈接更多精彩內(nèi)容