【javascript】Canvas繪圖詳解

Canvas繪圖

  • HTML5 的 canvas 元素使用 JavaScript 在網(wǎng)頁上繪制圖像。
  • 畫布是一個(gè)矩形區(qū)域,您可以控制其每一像素。
  • canvas 擁有多種繪制路徑、矩形、圓形、字符以及添加圖像的方法。
  • 瀏覽器支持
    • Internet Explorer 9、Firefox、Opera、Chrome 以及 Safari 支持<canvas> 及其屬性和方法。
    • 注釋:Internet Explorer 8 以及更早的版本不支持 <canvas> 元素。
  • HTML 5 Canvas 參考手冊

1、基本用法

(1)創(chuàng)建 Canvas 元素

  • 向 HTML5 頁面添加 canvas 元素。
  • 規(guī)定元素的 id、寬度和高度。
  • 開始和結(jié)束標(biāo)簽中的內(nèi)容是后備信息,如果瀏覽器不支持<canvas>元素,就會(huì)顯示這些信息。
<canvas id = "drawing" width = "200" height= "200">A drawing of something</canvas>

(2)通過 JavaScript 來繪制

  • canvas 元素本身是沒有繪圖能力的。所有的繪制工作必須在 JavaScript 內(nèi)部完成。
  • 要在這塊畫布(canvas)上繪圖,需要取得繪圖上下文。而取得繪圖上下文對象的引用,需要調(diào)用getContext()方法并傳入上下文的名字。
var drawing = document.getElementById("drawing");
//確定瀏覽器支持<canvas>元素
if (drawing.getContext){
    var context = drawing.getContext("2d");
    //更多代碼
}
  • 使用toDataURL()方法,可以導(dǎo)出在<canvas>元素上繪制的圖像。這個(gè)方法接受一個(gè)參數(shù),即圖像的MIME 類型格式,而且適合用于創(chuàng)建圖像的任何上下文。
var drawing = document.getElementById("drawing");
//確定瀏覽器支持<canvas>元素
if (drawing.getContext){

    //取得圖像的數(shù)據(jù)URI
    var imgURI = drawing.toDataURL("image/png");
    
    //顯示圖像
    var image = document.createElement("img");
    image.src = imgURI;
    document.body.appendChild(image);
}

2、2D上下文

  • 使用2D 繪圖上下文提供的方法,可以繪制簡單的2D 圖形,比如矩形、弧線和路徑。
  • 2D 上下文的坐標(biāo)開始于<canvas>元素的左上角,原點(diǎn)坐標(biāo)是(0,0)。所有坐標(biāo)值都基于這個(gè)原點(diǎn)計(jì)算,x 值越大表示越靠右,y 值越大表示越靠下。
  • 默認(rèn)情況下,width 和height 表示水平和垂直兩個(gè)方向上可用的像素?cái)?shù)目。

2.1 填充和描邊

  • 填充,就是用指定的樣式(顏色、漸變或圖像)填充圖形;
  • 描邊,就是只在圖形的邊緣畫線。
屬性 描述
fillStyle 設(shè)置或返回用于填充繪畫的顏色、漸變或模式
strokeStyle 設(shè)置或返回用于筆觸的顏色、漸變或模式
  • 這兩個(gè)屬性的值可以是字符串、漸變對象或模式對象,而且它們的默認(rèn)值都是"#000000"。
  • 如果為它們指定表示顏色的字符串值,可以使用CSS中指定顏色值的任何格式,包括顏色名、十六進(jìn)制碼、rgb、rgba、hsl 或hsla。
var drawing = document.getElementById("drawing");

//確定瀏覽器支持<canvas>元素
if (drawing.getContext){
    var context = drawing.getContext("2d");
    context.strokeStyle = "red";
    context.fillStyle = "#0000ff";
}

2.2 繪制矩形

  • 矩形是唯一一種可以直接在2D上下文中繪制的形狀。
  • 與矩形有關(guān)的有四個(gè)方法。
方法 描述
rect() 創(chuàng)建矩形
fillRect() 繪制“被填充”的矩形
strokeRect() 繪制矩形(無填充)
clearRect() 在給定的矩形內(nèi)清除指定的像素
  • 這幾個(gè)方法都能接收4個(gè)參數(shù)
參數(shù) 描述
x 矩形左上角的 x 坐標(biāo)
y 矩形左上角的 y 坐標(biāo)
width 矩形的寬度,以像素計(jì)
height 矩形的高度,以像素計(jì)
<!--示例畫布-->
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>

(1) rect()

  • 使用 stroke() 或 fill() 方法在畫布上實(shí)際地繪制矩形。
  • javascript 語法
context.rect(x,y,width,height);
  • 示例
/**通過 rect() 方法來創(chuàng)建三個(gè)矩形**/

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

// 紅色矩形
ctx.beginPath();
ctx.lineWidth="6";
ctx.strokeStyle="red";
ctx.rect(5,5,290,140);  
ctx.stroke();

// 綠色矩形
ctx.beginPath();
ctx.lineWidth="4";
ctx.strokeStyle="green";
ctx.rect(30,30,50,50);
ctx.stroke();

// 藍(lán)色矩形
ctx.beginPath();
ctx.lineWidth="10";
ctx.strokeStyle="blue";
ctx.rect(50,50,150,80);
ctx.stroke();
rect().png
rect().png

(2)fillRect()

  • fillRect()方法在畫布上繪制的矩形會(huì)填充指定的顏色。填充的顏色通過fillStyle 屬
    性指定。
  • javascript 語法
context.fillRect(x,y,width,height);
  • 示例
/**繪制填充矩形**/

var c=document.getElementById("myCanvas");
var context=c.getContext("2d");

//繪制紅色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);

//繪制半透明的藍(lán)色矩形
context.fillStyle = "rgba(0,0,255,0.5)";
context.fillRect(30, 30, 50, 50);
fillRect.png
fillRect.png

(3)strokeRect()

  • strokeRect() 方法繪制矩形(不填色)。筆觸的默認(rèn)顏色是黑色。
  • strokeRect()方法在畫布上繪制的矩形會(huì)使用指定的顏色描邊。描邊顏色通過strokeStyle 屬性指定。
  • javascript 語法
context.strokeRect(x,y,width,height);
  • 示例
var c=document.getElementById("myCanvas");
var context=c.getContext("2d");

//繪制紅色描邊矩形
context.strokeStyle = "#ff0000";
context.strokeRect(10, 10, 50, 50);
//繪制半透明的藍(lán)色描邊矩形
context.strokeStyle = "rgba(0,0,255,0.5)";
context.strokeRect(30, 30, 50, 50);
strokeRect.png
strokeRect.png

(4)clearRect()

  • clearRect()方法用于清除畫布上的矩形區(qū)域。
  • 本質(zhì)上,這個(gè)方法可以把繪制上下文中的某一矩形區(qū)域變透明。通過繪制形狀然后再清除指定區(qū)域,就可以生成有意思的效果。
  • javascript 語法
context.clearRect(x,y,width,height);
  • 示例
var c=document.getElementById("myCanvas");
var context=c.getContext("2d");

//繪制紅色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);

//繪制半透明的藍(lán)色矩形
context.fillStyle = "rgba(0,0,255,0.5)";
context.fillRect(30, 30, 50, 50);

//在兩個(gè)矩形重疊的地方清除一個(gè)小矩形
context.clearRect(40, 40, 10, 10);
clearRect.png
clearRect.png

2.3 繪制路徑

  • 2D 繪制上下文支持很多在畫布上繪制路徑的方法。通過路徑可以創(chuàng)造出復(fù)雜的形狀和線條。
方法 描述
fill() 填充當(dāng)前繪圖(路徑)
stroke() 繪制已定義的路徑
beginPath() 起始一條路徑,或重置當(dāng)前路徑
moveTo() 把路徑移動(dòng)到畫布中的指定點(diǎn),不創(chuàng)建線條
closePath() 創(chuàng)建從當(dāng)前點(diǎn)回到起始點(diǎn)的路徑
lineTo() 添加一個(gè)新點(diǎn),然后在畫布中創(chuàng)建從該點(diǎn)到最后指定點(diǎn)的線條
clip() 從原始畫布剪切任意形狀和尺寸的區(qū)域
quadraticCurveTo() 創(chuàng)建二次貝塞爾曲線
bezierCurveTo() 創(chuàng)建三次方貝塞爾曲線
arc() 創(chuàng)建弧/曲線(用于創(chuàng)建圓形或部分圓)
arcTo() 創(chuàng)建兩切線之間的弧/曲線
isPointInPath() 如果指定的點(diǎn)位于當(dāng)前路徑中,則返回 true,否則返回 false

(1)fill()

  • fill() 方法填充當(dāng)前的圖像(路徑)。默認(rèn)顏色是黑色。
  • 使用 fillStyle 屬性來填充另一種顏色/漸變。
  • javascript 語法
context.fill();
  • 示例
var c=document.getElementById("myCanvas");
var context = c.getContext('2d');
context.rect(20,20,150,100)
context.fillStyle = "green";
context.fill();
fill()
fill()

(2)stroke()

  • stroke() 方法會(huì)實(shí)際地繪制出通過moveTo()和lineTo()方法定義的路徑。默認(rèn)顏色是黑色。
  • 使用 strokeStyle 屬性來繪制另一種顏色/漸變。
  • javascript 語法
context.stroke();
  • 示例
var c=document.getElementById("myCanvas");
var context = c.getContext('2d');
context.beginPath();
context.moveTo(20,20);
context.lineTo(20,100);
context.lineTo(70,100);
context.strokeStyle = "green";
context.stroke();
stroke().png
stroke().png

(3)beginPath()、moveTo()、lineTo()

  • beginPath() 方法開始一條路徑,或重置當(dāng)前的路徑。
  • moveTo(x, y):將繪圖游標(biāo)移動(dòng)到(x,y),不畫線。
  • lineTo(x, y):從上一點(diǎn)開始繪制一條直線,到(x,y)為止。
  • javascript 語法
context.beginPath();
context.moveTo(x,y);
context.lineTo(x,y);
  • 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");

ctx.beginPath();              
ctx.strokeStyle="red";  // 綠色路徑
ctx.moveTo(0,75);
ctx.lineTo(300,75);
ctx.stroke();  // 進(jìn)行繪制

ctx.beginPath();
ctx.strokeStyle="blue";  // 紫色路徑
ctx.moveTo(150,0);
ctx.lineTo(150,150);            
ctx.stroke();  // 進(jìn)行繪制

beginPath()&moveTo()&lineTo().png
beginPath()&moveTo()&lineTo().png

(4)closePath()

  • closePath() 方法創(chuàng)建從當(dāng)前點(diǎn)到開始點(diǎn)的路徑。

  • 使用 stroke() 方法在畫布上繪制確切的路徑。

  • 使用 fill() 方法來填充圖像(默認(rèn)是黑色)。請使用fillStyle屬性來填充另一個(gè)顏色/漸變。

  • javascript 語法

context.closePath();
  • 示例
var c = document.getElementById("myCanvas");
var context = c.getContext('2d');
context.beginPath();
context.moveTo(20,20);
context.lineTo(20,100);
context.lineTo(100,100);
context.closePath();
context.stroke();
context.fillStyle = "green";
context.fill();
closePath().png
closePath().png

(5)clip()

  • clip() 方法從原始畫布中剪切任意形狀和尺寸。
  • javascript語法
context.clip();
  • 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
// Draw a rectangle
ctx.rect(50,20,200,120);
ctx.stroke();
// Draw green rectangle
ctx.fillStyle="green";
ctx.fillRect(0,0,150,100);

var c=document.getElementById("myCanvas2");
var ctx=c.getContext("2d");
// Clip a rectangular area
ctx.rect(50,20,200,120);
ctx.stroke();
ctx.clip();
// Draw red rectangle after clip()
ctx.fillStyle="red";
ctx.fillRect(0,0,150,100);
clip().png
clip().png

(6)quadraticCurveTo()

  • quadraticCurveTo() 方法通過使用表示二次貝塞爾曲線的指定控制點(diǎn),向當(dāng)前路徑添加一個(gè)點(diǎn)。

  • javascript 語法

context.quadraticCurveTo(cpx,cpy,x,y);
  • 從上一點(diǎn)開始繪制一條二次曲線,到(x,y)為止,并且以(cpx,cpy)作為控制點(diǎn)。

  • 示例

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);
ctx.quadraticCurveTo(20,100,200,20);
ctx.stroke();
quadraticCurveTo().png
quadraticCurveTo().png
  • 二次貝塞爾曲線需要兩個(gè)點(diǎn)。第一個(gè)點(diǎn)是用于二次貝塞爾計(jì)算中的控制點(diǎn),第二個(gè)點(diǎn)是曲線的結(jié)束點(diǎn)。
  • 曲線的開始點(diǎn)是當(dāng)前路徑中最后一個(gè)點(diǎn)。如果路徑不存在,那么請使用 beginPath() 和 moveTo() 方法來定義開始點(diǎn)。


    quadraticCurveTo分析.png
    quadraticCurveTo分析.png

(7)bezierCurveTo()

  • bezierCurveTo() 方法通過使用表示三次貝塞爾曲線的指定控制點(diǎn),向當(dāng)前路徑添加一個(gè)點(diǎn)。
  • javascript 語法
context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);
  • 從上一點(diǎn)開始繪制一條曲線,到(x,y)為止,并且以(cp1x,cp1y)和(cp2x,cp2y)為控制點(diǎn)。

  • 示例

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);
ctx.bezierCurveTo(20,100,200,100,200,20);
ctx.stroke();
bezierCurveTo().png
bezierCurveTo().png
  • 三次貝塞爾曲線需要三個(gè)點(diǎn)。前兩個(gè)點(diǎn)是用于三次貝塞爾計(jì)算中的控制點(diǎn),第三個(gè)點(diǎn)是曲線的結(jié)束點(diǎn)。
  • 曲線的開始點(diǎn)是當(dāng)前路徑中最后一個(gè)點(diǎn)。如果路徑不存在,那么請使用 beginPath() 和 moveTo() 方法來定義開始點(diǎn)。


    bezierCurveTo分析
    bezierCurveTo分析

(8)arc()

  • arc() 方法創(chuàng)建弧/曲線(用于創(chuàng)建圓或部分圓)。
  • javascript 語法
context.arc(x,y,r,sAngle,eAngle,counterclockwise);
  • 參數(shù)值
參數(shù) 描述
x 圓的中心的 x 坐標(biāo)。
y 圓的中心的 y 坐標(biāo)。
r 圓的半徑。
sAngle 起始角,以弧度計(jì)。(弧的圓形的三點(diǎn)鐘位置是 0 度)。
eAngle 結(jié)束角,以弧度計(jì)。
counterclockwise 可選。規(guī)定應(yīng)該逆時(shí)針還是順時(shí)針繪圖。False = 順時(shí)針,true = 逆時(shí)針。
  • 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.arc(100,75,50,0,2*Math.PI);
ctx.stroke();
arc().png
arc().png
  • 如需通過 arc() 來創(chuàng)建圓,請把起始角設(shè)置為 0,結(jié)束角設(shè)置為 2*Math.PI。
  • 使用 stroke() 或 fill() 方法在畫布上繪制實(shí)際的弧。


    arc()角度.png
    arc()角度.png

(9)arcTo()

  • arcTo() 方法在畫布上創(chuàng)建介于兩個(gè)切線之間的弧/曲線。
  • 從上一點(diǎn)開始繪制一條弧線,到(x2,y2)為止,并且以給定的半徑radius 穿過(x1,y1)。
  • javascript 語法
    context.arcTo(x1, y1, x2, y2, radius)
  • 示例
//獲取Canvas對象(畫布)
var canvas = document.getElementById("myCanvas");
if(canvas.getContext){  
    var ctx = canvas.getContext("2d");  
    ctx.moveTo(50, 50); 
    //端點(diǎn)1
    var p1 = {
        x : 200,
        y : 50
    };
    //端點(diǎn)2
    var p2 = {
        x : 200,
        y : 100         
    };
    //繪制與當(dāng)前端點(diǎn)、端點(diǎn)1、端點(diǎn)2三個(gè)點(diǎn)所形成的夾角的兩邊相切并且半徑為50px的圓的一段弧線
    ctx.arcTo(p1.x, p1.y, p2.x, p2.y, 50);
    ctx.strokeStyle = "blue";
    ctx.stroke();
}
atcTo().png
atcTo().png

(10)isPointInPath()

  • isPointInPath() 方法返回 true,如果指定的點(diǎn)位于當(dāng)前路徑中;否則返回 false。
  • javascrit 語法
context.isPointInPath(x,y);
  • 示例
var c=document.getElementById("myCanvas");
var context = c.getContext("2d");
context.rect(10,10,100,100);
if(context.isPointInPath(20,50)){
  context.stroke();
}
isPointInPath().png
isPointInPath().png

2.4 繪制文本

  • 2D 繪圖上下文提供了2個(gè)繪制文本方法和一個(gè)相關(guān)方法
  • fillText()和strokeText()都可以接收4個(gè)參數(shù):要繪制的文本字符串、x坐標(biāo)、y坐標(biāo)和可選的最大像素寬度。而measureText()接受一個(gè)參數(shù),表示要測量的文本。
方法 描述
fillText() 在畫布上繪制“被填充的”文本
strokeText() 在畫布上繪制文本(無填充)
measureText() 返回包含指定文本寬度的對象
  • 這兩個(gè)方法都以下列3 個(gè)屬性為基礎(chǔ)。
屬性 描述
font 設(shè)置或返回文本內(nèi)容的當(dāng)前字體屬性
textAlign 設(shè)置或返回文本內(nèi)容的當(dāng)前對齊方式,建議使用"start"和"end"
textBaseline 表示文本的基線,可以調(diào)整文本的垂直對齊方式

(1)fillText()

  • fillText() 方法在畫布上繪制填色的文本。文本的默認(rèn)顏色是黑色。
  • javascript 語法
context.fillText(text,x,y,maxWidth);
  • 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.font="30px Times new Roman";
ctx.fillStyle = "red"
ctx.fillText("Hello World!",10,50);
fillText().png
fillText().png

(2)strokeText()

  • strokeText() 方法在畫布上繪制文本(沒有填色)。文本的默認(rèn)顏色是黑色。
  • javascript 語法
context.strokeText(text,x,y,maxWidth);
  • 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.font="40px Times new Roman";
ctx.strokeStyle = "red";
ctx.strokeText("Hello World!",10,50);
strkeText().png
strkeText().png

(3)measureText()

  • measureText() 方法返回包含一個(gè)對象,該對象包含以像素計(jì)的指定字體寬度。
  • javascript 語法
context.measureText(text).width;
  • 示例
//在畫布上輸出文本之前,檢查字體的寬度
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.font="20px Arial";
var txt="Hello World"
ctx.fillText("width:" + ctx.measureText(txt).width,10,50);
ctx.fillText(txt,10,100);
measureText.png-
measureText.png-

(4)textAlign

  • textAlign 屬性根據(jù)錨點(diǎn),設(shè)置或返回文本內(nèi)容的當(dāng)前對齊方式。
  • javascript 語法
context.textAlign="center|end|left|right|start";
  • 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");

// Create a red line in position 150
ctx.strokeStyle="blue";
ctx.moveTo(150,20);
ctx.lineTo(150,170);
ctx.stroke();
ctx.font="15px Arial";   

// Show the different textAlign values
ctx.textAlign="start";      
ctx.fillText("textAlign=start",150,60);        
ctx.textAlign="end";      
ctx.fillText("textAlign=end",150,80);                  
ctx.textAlign="left";      
ctx.fillText("textAlign=left",150,100);
ctx.textAlign="center";     
ctx.fillText("textAlign=center",150,120);              
ctx.textAlign="right";      
ctx.fillText("textAlign=right",150,140);
textAlign.png
textAlign.png

(5)textBaseline

  • textBaseline 屬性設(shè)置或返回在繪制文本時(shí)的當(dāng)前文本基線。
  • javascript 語法
context.textBaseline="alphabetic|top|hanging|middle|ideographic|bottom";
  • 示例
textBaseline.png
textBaseline.png
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");

//Draw a red line at y=100
ctx.strokeStyle="blue";
ctx.moveTo(5,100);
ctx.lineTo(395,100);
ctx.stroke();

ctx.font="20px Arial"

//Place each word at y=100 with different textBaseline values
ctx.textBaseline="top"; 
ctx.fillText("Top",5,100); 
ctx.textBaseline="bottom"; 
ctx.fillText("Bottom",50,100); 
ctx.textBaseline="middle"; 
ctx.fillText("Middle",120,100); 
ctx.textBaseline="alphabetic"; 
ctx.fillText("Alphabetic",190,100); 
ctx.textBaseline="hanging"; 
ctx.fillText("Hanging",290,100); 
textBaseline.png
textBaseline.png

2.5 變換

  • 2D 繪制上下文支持各種基本的繪制變換。創(chuàng)建繪制上下文時(shí),會(huì)以默認(rèn)值初始化變換矩陣,在默認(rèn)的變換矩陣下,所有處理都按描述直接繪制。

  • 為繪制上下文應(yīng)用變換,會(huì)導(dǎo)致使用不同的變換矩陣應(yīng)用處理,從而產(chǎn)生不同的結(jié)果。

  • 可以通過如下方法來修改變換矩陣。

方法 描述
scale() 縮放當(dāng)前繪圖至更大或更小
rotate() 旋轉(zhuǎn)當(dāng)前繪圖
translate() 重新映射畫布上的 (0,0) 位置
transform() 替換繪圖的當(dāng)前轉(zhuǎn)換矩陣
setTransform() 將當(dāng)前轉(zhuǎn)換重置為單位矩陣。然后運(yùn)行 transform()

(1)scale()

  • scale() 方法縮放當(dāng)前繪圖,更大或更小。
  • 如果您對繪圖進(jìn)行縮放,所有之后的繪圖也會(huì)被縮放。定位也會(huì)被縮放。
  • javascript語法
context.scale(scalewidth,scaleheight);
  • 縮放圖像,在x 方向乘以scaleX,在y 方向乘以scaleY。scaleX和scaleY 的默認(rèn)值都是1.0。
  • 參數(shù)值
參數(shù) 描述
scalewidth 縮放當(dāng)前繪圖的寬度 (1=100%, 0.5=50%, 2=200%, 依次類推)
scaleheight 縮放當(dāng)前繪圖的高度 (1=100%, 0.5=50%, 2=200%, etc.)
/**依次放大**/
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");

ctx.strokeRect(5,5,25,15);
ctx.scale(2,2);
ctx.strokeRect(5,5,25,15);
ctx.scale(2,2);
ctx.strokeRect(5,5,25,15);
ctx.scale(2,2);
ctx.strokeRect(5,5,25,15);
scale().png
scale().png

(2)rotate()

  • rotate(angle),圍繞原點(diǎn)旋轉(zhuǎn)圖像angle 弧度。
  • javascript 語法
context.rotate(angle);
  • 參數(shù)值
    參數(shù)| 描述
    -|-
    angle |旋轉(zhuǎn)角度,以弧度計(jì)。如需將角度轉(zhuǎn)換為弧度,請使用degreesMath.PI/180 公式進(jìn)行計(jì)算。舉例:如需旋轉(zhuǎn) 5 度,可規(guī)定下面的公式:5Math.PI/180。
  • 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.rotate(20*Math.PI/180);
ctx.fillRect(50,20,100,50);
rotate().png
rotate().png

(3)translate()

  • translate(x, y):將坐標(biāo)原點(diǎn)移動(dòng)到(x,y)。執(zhí)行這個(gè)變換之后,坐標(biāo)(0,0)會(huì)變成之前由(x,y)表示的點(diǎn)。
  • javascript語法
context.translate(x,y);
  • 示例
/**繪制一個(gè)簡易的時(shí)鐘**/
var c=document.getElementById("myCanvas");
var ctx = c.getContext("2d");

ctx.beginPath();
ctx.arc(150,75,70,0,2*Math.PI);
ctx.stroke();

ctx.moveTo(215,75);
ctx.arc(150,75,65,0,2*Math.PI);
//變換原點(diǎn)
ctx.translate(150,75);

ctx.textBaseline = "middle";
ctx.fillText('3',50,0);
ctx.textAlign="center";  
ctx.fillText('6',0,55);
ctx.fillText('9',-50,0);
ctx.fillText('12',0,-55);

ctx.moveTo(0,0);
ctx.lineTo(35,0);
ctx.moveTo(0,0);
ctx.lineTo(0,-50);

ctx.stroke();
translate().png
translate().png

(4)transform()

  • 畫布上的每個(gè)對象都擁有一個(gè)當(dāng)前的變換矩陣。
  • transform() 方法替換當(dāng)前的變換矩陣。它以下面描述的矩陣來操作當(dāng)前的變換矩陣
a  c  e
b  d  f
0  0  1
  • transform() 允許您縮放、旋轉(zhuǎn)、移動(dòng)并傾斜當(dāng)前的環(huán)境。
  • javascript語法
context.transform(a,b,c,d,e,f);
  • 參數(shù)值
    參數(shù)| 描述
    -|-
    a| 水平縮放繪圖
    b| 水平傾斜繪圖
    c| 垂直傾斜繪圖
    d| 垂直縮放繪圖
    e| 水平移動(dòng)繪圖
    f| 垂直移動(dòng)繪圖
  • 示例


    矩陣公式
    矩陣公式
  • 由此可見,transform(x, 0, 0, y, 0, 0),等同于scale(x,y); transform(1, 0, 0, 1, x, y),等同于translate(x,y);
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");

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

//等同于translate(x,y)
ctx.transform(1,0,0,1,30,30);
ctx.strokeStyle="red";
ctx.strokeRect(0,0,100,30);

//等同于scale(2,2)
ctx.transform(2,0,0,2,0,0);
ctx.strokeStyle="blue";
ctx.strokeRect(0,0,100,30);

//水平和豎直方向傾斜
ctx.transform(1,0.5,0.5,1,0,0);
ctx.strokeStyle="black";
ctx.strokeRect(0,0,100,30);
transform().png
transform().png

(5)setTransform()

  • setTransform() 方法把當(dāng)前的變換矩陣重置為單位矩陣,然后以相同的參數(shù)運(yùn)行 transform()。
  • javascript語法
context.setTransform(a,b,c,d,e,f);
  • 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");

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

//等同于translate(x,y)
ctx.setTransform(1,0,0,1,30,30);
ctx.strokeStyle="red";
ctx.strokeRect(0,0,100,30);

//等同于scale(2,2)
ctx.setTransform(2,0,0,2,0,0);
ctx.strokeStyle="blue";
ctx.strokeRect(0,0,100,30);

//水平和豎直方向傾斜
ctx.setTransform(1,0.5,0.5,1,0,0);
ctx.strokeStyle="black";
ctx.strokeRect(0,0,100,30);
setTransform().png
setTransform().png

2.6 繪制圖像

  • drawImage() 方法在畫布上繪制圖像、畫布或視頻。
  • drawImage() 方法也能夠繪制圖像的某些部分,以及/或者增加或減少圖像的尺寸。
  • JavaScript 語法
/***語法一,在畫布上定位圖像*/
context.drawImage(img,x,y);

/**語法二,在畫布上定位圖像,并規(guī)定圖像的寬度和高度**/
context.drawImage(img,x,y,width,height);

/**語法三,剪切圖像,并在畫布上定位被剪切的部分**/
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
  • 參數(shù)值
參數(shù) 描述
img 規(guī)定要使用的圖像、畫布或視頻。
sx 可選。開始剪切的 x 坐標(biāo)位置。
sy 可選。開始剪切的 y 坐標(biāo)位置。
swidth 可選。被剪切圖像的寬度。
sheight 可選。被剪切圖像的高度。
x 在畫布上放置圖像的 x 坐標(biāo)位置。
y 在畫布上放置圖像的 y 坐標(biāo)位置。
width 可選。要使用的圖像的寬度。(伸展或縮小圖像)

height 可選。要使用的圖像的高度。(伸展或縮小圖像)

  • 示例
<img src="http://www.w3school.com.cn/i/eg_tulip.jpg" alt="tulip" id="tulip" style="margin-left:0px;" />
document.getElementById("tulip").onload=function(){
  var c=document.getElementById("myCanvas");
  var ctx=c.getContext("2d");
  var img=document.getElementById("tulip");
  ctx.drawImage(img,90,130,90,80,20,20,90,80);
};
drawImage.png
drawImage.png

2.7 陰影

  • 2D 上下文會(huì)根據(jù)以下幾個(gè)屬性的值,自動(dòng)為形狀或路徑繪制出陰影。
屬性 描述
shadowColor 用CSS 顏色格式表示的陰影顏色,默認(rèn)為黑色。
shadowBlur 模糊的像素?cái)?shù),默認(rèn)0,即不模糊。
shadowOffsetX 形狀或路徑x 軸方向的陰影偏移量,默認(rèn)為0。
shadowOffsetY 形狀或路徑y(tǒng) 軸方向的陰影偏移量,默認(rèn)為0。
  • 示例
var c=document.getElementById("myCanvas");
var context=c.getContext("2d");
//設(shè)置陰影
context.shadowOffsetX = 15;
context.shadowOffsetY = 15;
context.shadowBlur = 5;
context.shadowColor = "rgba(0, 0, 0, 0.5)";
//繪制紅色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
//繪制藍(lán)色矩形
context.fillStyle = "rgba(0,0,255,1)";
context.fillRect(30, 30, 50, 50);
陰影
陰影

2.8 漸變

  • 漸變由CanvasGradient 實(shí)例表示,很容易通過2D 上下文來創(chuàng)建和修改。
    方法| 描述
    -|-
    createLinearGradient()| 創(chuàng)建線性漸變(用在畫布內(nèi)容上)
    createRadialGradient()| 創(chuàng)建放射狀/環(huán)形的漸變(用在畫布內(nèi)容上)
    addColorStop() |規(guī)定漸變對象中的顏色和停止位置

(1)createLinearGradient()

  • createLinearGradient() 方法創(chuàng)建線性的漸變對象。
  • 漸變可用于填充矩形、圓形、線條、文本等等
  • JavaScript 語法
context.createLinearGradient(x0,y0,x1,y1);
  • 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");

var grd=ctx.createLinearGradient(0,0,170,0);
grd.addColorStop(0,"white");
grd.addColorStop(1,"red");

ctx.fillStyle=grd;
ctx.fillRect(20,20,150,100);
線性漸變
線性漸變

(2)createRadialGradient()

  • createLinearGradient() 方法創(chuàng)建放射狀/圓形漸變對象。
  • 漸變可用于填充矩形、圓形、線條、文本等等。
  • JavaScript 語法
context.createRadialGradient(x0,y0,r0,x1,y1,r1);
  • 示例
var c=document.getElementById("myCanvas");
var context=c.getContext("2d");
var gradient = context.createRadialGradient(55, 55, 10, 55, 55, 30);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "red");

//繪制漸變矩形
context.fillStyle = gradient;
context.fillRect(30, 30, 150, 100);
圓形漸變
圓形漸變

2.9 模式

  • createPattern() 方法在指定的方向內(nèi)重復(fù)指定的元素。
  • 元素可以是圖片、視頻,或者其他 <canvas> 元素。
  • 被重復(fù)的元素可用于繪制/填充矩形、圓形或線條等等。
  • JavaScript 語法
context.createPattern(image,"repeat|repeat-x|repeat-y|no-repeat");
  • 示例
<img src="http://www.w3school.com.cn/i/lamp.gif" id="lamp" />
var c=document.getElementById("myCanvas");
var context=c.getContext("2d");
var image = document.getElementById("lamp"),
pattern = context.createPattern(image, "repeat");
//繪制矩形
context.fillStyle = pattern;
context.fillRect(0, 0, 160, 130);
createPattern()
createPattern()

2.10 像素操作與使用圖像數(shù)據(jù)

  • 2D 上下文 支持像素操作和使用圖像數(shù)據(jù)
方法 描述
createImageData() 創(chuàng)建新的、空白的 ImageData 對象
getImageData() 返回 ImageData 對象,該對象為畫布上指定的矩形復(fù)制像素?cái)?shù)據(jù)
putImageData() 把圖像數(shù)據(jù)(從指定的 ImageData 對象)放回畫布上
  • 每個(gè)ImageData 對象都有三個(gè)屬性:width、height 和data
屬性 描述
width 返回 ImageData 對象的寬度
height 返回 ImageData 對象的高度
data 返回一個(gè)對象,其包含指定的 ImageData 對象的圖像數(shù)據(jù)
  • data 屬性是一個(gè)數(shù)組,保存著圖像中每一個(gè)像素的數(shù)據(jù)。對于ImageData對象中的每個(gè)像素,都存在著四方面的信息,即 RGBA 值:
元素
R 紅色 (0-255)
G 綠色 (0-255)
B 藍(lán)色 (0-255)
A alpha 通道 (0-255; 0 是透明的,255 是完全可見的)

(1)createImageData()

  • createImageData() 方法創(chuàng)建新的空白 ImageData 對象。新對象的默認(rèn)像素值 transparent black。
  • javascript 語法
/**語法一,以指定的尺寸(以像素計(jì))創(chuàng)建新的 ImageData 對象**/
var imgData=context.createImageData(width,height);

/**語法二,創(chuàng)建與指定的另一個(gè) ImageData 對象尺寸相同的新 ImageData 對象(不會(huì)復(fù)制圖像數(shù)據(jù))**/
var imgData=context.createImageData(imageData);
  • 示例
/**創(chuàng)建 100*100 像素的 ImageData 對象,其中每個(gè)像素都是綠色的,然后把它放到畫布上**/
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var imgData=ctx.createImageData(100,100);
for (var i=0;i<imgData.data.length;i+=4)
  {
  imgData.data[i+0]=0;
  imgData.data[i+1]=255;
  imgData.data[i+2]=0;
  imgData.data[i+3]=255;
  }
ctx.putImageData(imgData,10,10);
createImageData().png
createImageData().png

(2)getImageData()、putImageData()

  • getImageData() 方法返回ImageData對象,該對象拷貝了畫布指定矩形的像素?cái)?shù)據(jù)。
  • putImageData() 方法將圖像數(shù)據(jù)(從指定的 ImageData 對象)放回畫布上。
  • javascript 語法
var imgData=context.getImageData(x,y,width,height);
context.putImageData(imgData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight);
  • 示例
<img src="http://www.w3school.com.cn/i/eg_tulip.jpg" alt="tulip" id="tulip" style="margin-left:0px;" />
/**使用 getImageData() 來反轉(zhuǎn)畫布上的圖像的每個(gè)像素的顏色**/
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = document.getElementById("tulip");
ctx.drawImage(img,0,0);
var imgData = ctx.getImageData(0,0,c.width,c.height);
for(var i= 0; i<imgData.data.length; i+=4){
    imgData.data[i] = 255-imgData.data[i];
    imgData.data[i+1] = 255- imgData.data[i+1];
    imgData.data[i+2] = 255-imgData.data[i+2];
    imgData.data[i+3] = 255;
}
ctx.putImageData(imgData,0,0);
反色
反色

2.11合成

  • 有兩個(gè)會(huì)應(yīng)用到2D 上下文中所有繪制操作的屬性:globalAlpha和globalComposition-Operation
屬性 描述
globalAlpha 設(shè)置或返回繪圖的當(dāng)前 alpha 或透明值
globalCompositeOperation 設(shè)置或返回新圖像如何繪制到已有的圖像上

(1)globalAlpha()

  • globalAlpha 屬性設(shè)置或返回繪圖的當(dāng)前透明值(alpha 或 transparency)。

  • globalAlpha 是一個(gè)介于0 和1 之間的值(包括0 和1),用于指定所有繪制的透
    明度。默認(rèn)值為0。

  • javascript 語法

context.globalAlpha=number;
  • 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle="red";
ctx.fillRect(20,20,75,50);
// 調(diào)節(jié)透明度
ctx.globalAlpha=0.2;
ctx.fillStyle="blue";
ctx.fillRect(50,50,75,50);
ctx.fillStyle="green";
ctx.fillRect(80,80,75,50);
globalAlpha().png
globalAlpha().png

(2)globalCompositeOperation()

  • globalCompositeOperation屬性設(shè)置或返回如何將一個(gè)源(新的)圖像繪制到目標(biāo)(已有)的圖像上。
  • 源圖像 = 您打算放置到畫布上的繪圖。
  • 目標(biāo)圖像 = 您已經(jīng)放置在畫布上的繪圖。
  • javascript 語法
context.globalCompositeOperation="source-in";
  • 屬性值
描述
source-over 默認(rèn)。在目標(biāo)圖像上顯示源圖像。
source-atop 在目標(biāo)圖像頂部顯示源圖像。源圖像位于目標(biāo)圖像之外的部分是不可見的。
source-in 在目標(biāo)圖像中顯示源圖像。只有目標(biāo)圖像內(nèi)的源圖像部分會(huì)顯示,目標(biāo)圖像是透明的。
source-out 在目標(biāo)圖像之外顯示源圖像。只會(huì)顯示目標(biāo)圖像之外源圖像部分,目標(biāo)圖像是透明的。
destination-over 在源圖像上方顯示目標(biāo)圖像。
destination-atop 在源圖像頂部顯示目標(biāo)圖像。源圖像之外的目標(biāo)圖像部分不會(huì)被顯示。
destination-in 在源圖像中顯示目標(biāo)圖像。只有源圖像內(nèi)的目標(biāo)圖像部分會(huì)被顯示,源圖像是透明的。
destination-out 在源圖像外顯示目標(biāo)圖像。只有源圖像外的目標(biāo)圖像部分會(huì)被顯示,源圖像是透明的。
lighter 顯示源圖像 + 目標(biāo)圖像。
copy 顯示源圖像。忽略目標(biāo)圖像。
xor 使用異或操作對源圖像與目標(biāo)圖像進(jìn)行組合。
  • 示例
<!DOCTYPE html>
<html>
    <head>
        <style>
            canvas{
                border:1px solid #d3d3d3;
                margin-right:10px;
                margin-bottom:20px; 
            }
        </style>
    </head>
    <body>
    <script>
        var gco=new Array();
        gco.push("source-atop");
        gco.push("source-in");
        gco.push("source-out");
        gco.push("source-over");
        gco.push("destination-atop");
        gco.push("destination-in");
        gco.push("destination-out");
        gco.push("destination-over");
        gco.push("lighter");
        gco.push("copy");
        gco.push("xor");
        for (n=0;n<gco.length;n++)
            {
                document.write("<div id='p_" + n + "' style='float:left;'>" + gco[n] + ":<br>");
                var c=document.createElement("canvas");
                c.width=120;
                c.height=100;
                document.getElementById("p_" + n).appendChild(c);
                var ctx=c.getContext("2d");    
                ctx.fillStyle="blue";
                ctx.fillRect(10,10,50,50);
                ctx.globalCompositeOperation=gco[n];
                ctx.beginPath();
                ctx.fillStyle="red";
                ctx.arc(50,50,30,0,2*Math.PI);
                ctx.fill();
                document.write("</div>");   
            }
    </script>
</body>
</html>
globalCompositeOperation.png
globalCompositeOperation.png

2.12 線條樣式

  • 2D 上下文中繪制操作中還具有相應(yīng)的線條樣式屬性。
    屬性| 描述
    -|-
    lineCap| 設(shè)置或返回線條的結(jié)束端點(diǎn)樣式
    lineJoin| 設(shè)置或返回兩條線相交時(shí),所創(chuàng)建的拐角類型
    lineWidth| 設(shè)置或返回當(dāng)前的線條寬度
    miterLimit| 設(shè)置或返回最大斜接長度

(1)lineWidth

  • lineWidth 屬性設(shè)置或返回當(dāng)前線條的寬度,以像素計(jì)。
  • javascript語法
context.lineWidth=number;
  • 示例
//用寬度為 10 像素的線條來繪制矩形
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.lineWidth=10;
ctx.strokeRect(20,20,80,100);
lineWidth
lineWidth

(2)lineCap

  • lineCap 屬性設(shè)置或返回線條末端線帽的樣式。
  • javascript 語法
    context.lineCap="butt|round|square";
  • 屬性值
描述
butt 默認(rèn)。向線條的每個(gè)末端添加平直的邊緣。
round 向線條的每個(gè)末端添加圓形線帽。
square 向線條的每個(gè)末端添加正方形線帽。
  • 示例
//三種不同的線帽
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");

ctx.beginPath();
ctx.lineWidth=10;
ctx.lineCap="butt";
ctx.moveTo(20,20);
ctx.lineTo(200,20);
ctx.stroke();

ctx.beginPath();
ctx.lineCap="round";
ctx.moveTo(20,40);
ctx.lineTo(200,40);
ctx.stroke();

ctx.beginPath();
ctx.lineCap="square";
ctx.moveTo(20,60);
ctx.lineTo(200,60);
ctx.stroke();
linCap
linCap

(2)lineJoin

  • lineJoin 屬性設(shè)置或返回所創(chuàng)建邊角的類型,當(dāng)兩條線交匯時(shí)。
  • javascript語法
context.lineJoin="bevel|round|miter";
  • 屬性值
描述
bevel 創(chuàng)建斜角。
round 創(chuàng)建圓角。
miter 默認(rèn)。創(chuàng)建尖角
  • 示例
/**當(dāng)兩條線條交匯時(shí),分別創(chuàng)建斜角、圓形、尖角邊角**/
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.lineWidth=20;
ctx.lineJoin="bevel";
ctx.moveTo(20,20);
ctx.lineTo(100,50);
ctx.lineTo(20,100);
ctx.stroke();

ctx.beginPath();
ctx.lineWidth=20;
ctx.lineJoin="round";
ctx.moveTo(100,20);
ctx.lineTo(180,50);
ctx.lineTo(100,100);
ctx.stroke();

ctx.beginPath();
ctx.lineWidth=20;
ctx.lineJoin="miter";
ctx.moveTo(180,20);
ctx.lineTo(260,50);
ctx.lineTo(180,100);
ctx.stroke();
lineJoin
lineJoin

(4)miterLimit

  • miterLimit 屬性設(shè)置或返回最大斜接長度。

  • 斜接長度指的是在兩條線交匯處內(nèi)角和外角之間的距離。


    斜度
    斜度
  • 只有當(dāng) lineJoin 屬性為 "miter" 時(shí),miterLimit 才有效。

  • 邊角的角度越小,斜接長度就會(huì)越大。

  • 為了避免斜接長度過長,我們可以使用 miterLimit 屬性。

  • 如果斜接長度超過 miterLimit 的值,邊角會(huì)以 lineJoin 的 "bevel" 類型來顯示

斜角
斜角
  • javascript語法
context.miterLimit=number;
  • 示例
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.lineWidth=10;
ctx.lineJoin="miter";
ctx.beginPath();
ctx.miterLimit=5;
ctx.moveTo(20,20);
ctx.lineTo(50,27);
ctx.lineTo(20,34);
ctx.stroke();
ctx.beginPath();
ctx.miterLimit=3;
ctx.moveTo(80,20);
ctx.lineTo(110,27);
ctx.lineTo(80,34);
ctx.stroke();
miterLimit
miterLimit

2.13 其它

  • 有兩個(gè)方法可以跟蹤上下文的狀態(tài)變化。
  • 如果你知道將來還要返回某組屬性與變換的組合,可以調(diào)用save()方法。調(diào)用這個(gè)方法后,當(dāng)時(shí)的所有設(shè)置都會(huì)進(jìn)入一個(gè)棧結(jié)構(gòu),得以妥善保管。
  • 然后可以對上下文進(jìn)行其他修改。等想要回到之前保存的設(shè)置時(shí),可以調(diào)用restore()方法,在保存設(shè)置的棧結(jié)構(gòu)中向前返回一級(jí),恢復(fù)之前的狀態(tài)。
  • 連續(xù)調(diào)用save()可以把更多設(shè)置保存到棧結(jié)構(gòu)中,之后再連續(xù)調(diào)用restore()則可以一級(jí)一級(jí)返回。
var c=document.getElementById("myCanvas");
var context=c.getContext("2d");
context.strokeStyle = "red";
context.translate(10, 10);
context.save();

context.strokeStyle = "blue";
context.translate(40, 40);
context.save();

context.strokeStyle = "green";
context.strokeRect(0, 0, 20, 20); //繪制綠色矩形
context.restore();

context.strokeRect(40, 40, 20, 20); //繪制藍(lán)色矩形
context.restore();

context.strokeRect(0, 0, 20, 20); //繪制紅色矩形
save()&restore()
save()&restore()
好好學(xué)習(xí)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 一:canvas簡介 1.1什么是canvas? ①:canvas是HTML5提供的一種新標(biāo)簽 ②:HTML5 ...
    GreenHand1閱讀 4,882評(píng)論 2 32
  • 本章內(nèi)容 理解 元素 繪制簡單的 2D 圖形 使用 WebGL 繪制 3D 圖形 這個(gè)元素負(fù)責(zé)在頁面中設(shè)定一個(gè)區(qū)域...
    悶油瓶小張閱讀 987評(píng)論 0 0
  • 一、簡介 HTML5 中的定義:“它是依賴分辨率的位圖畫布,你可以在 canvas 上面繪制任何圖形,甚至加載照片...
    destiny0904閱讀 10,834評(píng)論 1 4
  • Core Graphics Framework是一套基于C的API框架,使用了Quartz作為繪圖引擎。它提供了低...
    ShanJiJi閱讀 1,723評(píng)論 0 20
  • 【喪失當(dāng)下的時(shí)刻:幻象的核心】 從時(shí)間解脫就是:從你在過去中尋找認(rèn)同感的心理需要以及在未來尋找滿足的心理需要中解放...
    霸道學(xué)習(xí)閱讀 701評(píng)論 0 1

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