【javascript】Canvas繪圖詳解

weixin_34290000發表於2017-12-29

Canvas繪圖

  • HTML5 的 canvas 元素使用 JavaScript 在網頁上繪製影象。
  • 畫布是一個矩形區域,您可以控制其每一畫素。
  • canvas 擁有多種繪製路徑、矩形、圓形、字元以及新增影象的方法。
  • 瀏覽器支援
    • Internet Explorer 9、Firefox、Opera、Chrome 以及 Safari 支援<canvas> 及其屬性和方法。
    • 註釋:Internet Explorer 8 以及更早的版本不支援 <canvas> 元素。
  • HTML 5 Canvas 參考手冊

1、基本用法

(1)建立 Canvas 元素

  • 向 HTML5 頁面新增 canvas 元素。
  • 規定元素的 id、寬度和高度。
  • 開始和結束標籤中的內容是後備資訊,如果瀏覽器不支援<canvas>元素,就會顯示這些資訊。
<canvas id = "drawing" width = "200" height= "200">A drawing of something</canvas>

(2)通過 JavaScript 來繪製

  • canvas 元素本身是沒有繪圖能力的。所有的繪製工作必須在 JavaScript 內部完成。
  • 要在這塊畫布(canvas)上繪圖,需要取得繪圖上下文。而取得繪圖上下文物件的引用,需要呼叫getContext()方法並傳入上下文的名字。
var drawing = document.getElementById("drawing");
//確定瀏覽器支援<canvas>元素
if (drawing.getContext){
    var context = drawing.getContext("2d");
    //更多程式碼
}
  • 使用toDataURL()方法,可以匯出在<canvas>元素上繪製的影象。這個方法接受一個引數,即影象的MIME 型別格式,而且適合用於建立影象的任何上下文。
var drawing = document.getElementById("drawing");
//確定瀏覽器支援<canvas>元素
if (drawing.getContext){

    //取得影象的資料URI
    var imgURI = drawing.toDataURL("image/png");
    
    //顯示影象
    var image = document.createElement("img");
    image.src = imgURI;
    document.body.appendChild(image);
}

2、2D上下文

  • 使用2D 繪圖上下文提供的方法,可以繪製簡單的2D 圖形,比如矩形、弧線和路徑。
  • 2D 上下文的座標開始於<canvas>元素的左上角,原點座標是(0,0)。所有座標值都基於這個原點計算,x 值越大表示越靠右,y 值越大表示越靠下。
  • 預設情況下,width 和height 表示水平和垂直兩個方向上可用的畫素數目。

2.1 填充和描邊

  • 填充,就是用指定的樣式(顏色、漸變或影象)填充圖形;
  • 描邊,就是隻在圖形的邊緣畫線。
屬性 描述
fillStyle 設定或返回用於填充繪畫的顏色、漸變或模式
strokeStyle 設定或返回用於筆觸的顏色、漸變或模式
  • 這兩個屬性的值可以是字串、漸變物件或模式物件,而且它們的預設值都是"#000000"。
  • 如果為它們指定表示顏色的字串值,可以使用CSS中指定顏色值的任何格式,包括顏色名、十六進位制碼、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上下文中繪製的形狀。
  • 與矩形有關的有四個方法。
方法 描述
rect() 建立矩形
fillRect() 繪製“被填充”的矩形
strokeRect() 繪製矩形(無填充)
clearRect() 在給定的矩形內清除指定的畫素
  • 這幾個方法都能接收4個引數
引數 描述
x 矩形左上角的 x 座標
y 矩形左上角的 y 座標
width 矩形的寬度,以畫素計
height 矩形的高度,以畫素計
<!--示例畫布-->
<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() 方法在畫布上實際地繪製矩形。
  • javascript 語法
context.rect(x,y,width,height);
  • 示例
/**通過 rect() 方法來建立三個矩形**/

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();

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

(2)fillRect()

  • fillRect()方法在畫布上繪製的矩形會填充指定的顏色。填充的顏色通過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);

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

(3)strokeRect()

  • strokeRect() 方法繪製矩形(不填色)。筆觸的預設顏色是黑色。
  • strokeRect()方法在畫布上繪製的矩形會使用指定的顏色描邊。描邊顏色通過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);
//繪製半透明的藍色描邊矩形
context.strokeStyle = "rgba(0,0,255,0.5)";
context.strokeRect(30, 30, 50, 50);
strokeRect.png

(4)clearRect()

  • clearRect()方法用於清除畫布上的矩形區域。
  • 本質上,這個方法可以把繪製上下文中的某一矩形區域變透明。通過繪製形狀然後再清除指定區域,就可以生成有意思的效果。
  • 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);

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

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

2.3 繪製路徑

  • 2D 繪製上下文支援很多在畫布上繪製路徑的方法。通過路徑可以創造出複雜的形狀和線條。
方法 描述
fill() 填充當前繪圖(路徑)
stroke() 繪製已定義的路徑
beginPath() 起始一條路徑,或重置當前路徑
moveTo() 把路徑移動到畫布中的指定點,不建立線條
closePath() 建立從當前點回到起始點的路徑
lineTo() 新增一個新點,然後在畫布中建立從該點到最後指定點的線條
clip() 從原始畫布剪下任意形狀和尺寸的區域
quadraticCurveTo() 建立二次貝塞爾曲線
bezierCurveTo() 建立三次方貝塞爾曲線
arc() 建立弧/曲線(用於建立圓形或部分圓)
arcTo() 建立兩切線之間的弧/曲線
isPointInPath() 如果指定的點位於當前路徑中,則返回 true,否則返回 false

(1)fill()

  • fill() 方法填充當前的影象(路徑)。預設顏色是黑色。
  • 使用 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()

(2)stroke()

  • stroke() 方法會實際地繪製出通過moveTo()和lineTo()方法定義的路徑。預設顏色是黑色。
  • 使用 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

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

  • beginPath() 方法開始一條路徑,或重置當前的路徑。
  • moveTo(x, y):將繪圖遊標移動到(x,y),不畫線。
  • lineTo(x, y):從上一點開始繪製一條直線,到(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();  // 進行繪製

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

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

(4)closePath()

  • closePath() 方法建立從當前點到開始點的路徑。

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

  • 使用 fill() 方法來填充影象(預設是黑色)。請使用fillStyle屬性來填充另一個顏色/漸變。

  • 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

(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

(6)quadraticCurveTo()

  • quadraticCurveTo() 方法通過使用表示二次貝塞爾曲線的指定控制點,向當前路徑新增一個點。

  • javascript 語法

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

  • 示例

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
  • 二次貝塞爾曲線需要兩個點。第一個點是用於二次貝塞爾計算中的控制點,第二個點是曲線的結束點。
  • 曲線的開始點是當前路徑中最後一個點。如果路徑不存在,那麼請使用 beginPath() 和 moveTo() 方法來定義開始點。


    quadraticCurveTo分析.png

(7)bezierCurveTo()

  • bezierCurveTo() 方法通過使用表示三次貝塞爾曲線的指定控制點,向當前路徑新增一個點。
  • javascript 語法
context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);
  • 從上一點開始繪製一條曲線,到(x,y)為止,並且以(cp1x,cp1y)和(cp2x,cp2y)為控制點。

  • 示例

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
  • 三次貝塞爾曲線需要三個點。前兩個點是用於三次貝塞爾計算中的控制點,第三個點是曲線的結束點。
  • 曲線的開始點是當前路徑中最後一個點。如果路徑不存在,那麼請使用 beginPath() 和 moveTo() 方法來定義開始點。


    bezierCurveTo分析

(8)arc()

  • arc() 方法建立弧/曲線(用於建立圓或部分圓)。
  • javascript 語法
context.arc(x,y,r,sAngle,eAngle,counterclockwise);
  • 引數值
引數 描述
x 圓的中心的 x 座標。
y 圓的中心的 y 座標。
r 圓的半徑。
sAngle 起始角,以弧度計。(弧的圓形的三點鐘位置是 0 度)。
eAngle 結束角,以弧度計。
counterclockwise 可選。規定應該逆時針還是順時針繪圖。False = 順時針,true = 逆時針。
  • 示例
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() 來建立圓,請把起始角設定為 0,結束角設定為 2*Math.PI。
  • 使用 stroke() 或 fill() 方法在畫布上繪製實際的弧。


    arc()角度.png

(9)arcTo()

  • arcTo() 方法在畫布上建立介於兩個切線之間的弧/曲線。
  • 從上一點開始繪製一條弧線,到(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); 
    //端點1
    var p1 = {
        x : 200,
        y : 50
    };
    //端點2
    var p2 = {
        x : 200,
        y : 100         
    };
    //繪製與當前端點、端點1、端點2三個點所形成的夾角的兩邊相切並且半徑為50px的圓的一段弧線
    ctx.arcTo(p1.x, p1.y, p2.x, p2.y, 50);
    ctx.strokeStyle = "blue";
    ctx.stroke();
}
atcTo().png

(10)isPointInPath()

  • isPointInPath() 方法返回 true,如果指定的點位於當前路徑中;否則返回 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

2.4 繪製文字

  • 2D 繪圖上下文提供了2個繪製文字方法和一個相關方法
  • fillText()和strokeText()都可以接收4個引數:要繪製的文字字串、x座標、y座標和可選的最大畫素寬度。而measureText()接受一個引數,表示要測量的文字。
方法 描述
fillText() 在畫布上繪製“被填充的”文字
strokeText() 在畫布上繪製文字(無填充)
measureText() 返回包含指定文字寬度的物件
  • 這兩個方法都以下列3 個屬性為基礎。
屬性 描述
font 設定或返回文字內容的當前字型屬性
textAlign 設定或返回文字內容的當前對齊方式,建議使用"start"和"end"
textBaseline 表示文字的基線,可以調整文字的垂直對齊方式

(1)fillText()

  • fillText() 方法在畫布上繪製填色的文字。文字的預設顏色是黑色。
  • 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

(2)strokeText()

  • strokeText() 方法在畫布上繪製文字(沒有填色)。文字的預設顏色是黑色。
  • 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

(3)measureText()

  • measureText() 方法返回包含一個物件,該物件包含以畫素計的指定字型寬度。
  • 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-

(4)textAlign

  • textAlign 屬性根據錨點,設定或返回文字內容的當前對齊方式。
  • 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

(5)textBaseline

  • textBaseline 屬性設定或返回在繪製文字時的當前文字基線。
  • javascript 語法
context.textBaseline="alphabetic|top|hanging|middle|ideographic|bottom";
  • 示例
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

2.5 變換

  • 2D 繪製上下文支援各種基本的繪製變換。建立繪製上下文時,會以預設值初始化變換矩陣,在預設的變換矩陣下,所有處理都按描述直接繪製。

  • 為繪製上下文應用變換,會導致使用不同的變換矩陣應用處理,從而產生不同的結果。

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

方法 描述
scale() 縮放當前繪圖至更大或更小
rotate() 旋轉當前繪圖
translate() 重新對映畫布上的 (0,0) 位置
transform() 替換繪圖的當前轉換矩陣
setTransform() 將當前轉換重置為單位矩陣。然後執行 transform()

(1)scale()

  • scale() 方法縮放當前繪圖,更大或更小。
  • 如果您對繪圖進行縮放,所有之後的繪圖也會被縮放。定位也會被縮放。
  • javascript語法
context.scale(scalewidth,scaleheight);
  • 縮放影象,在x 方向乘以scaleX,在y 方向乘以scaleY。scaleX和scaleY 的預設值都是1.0。
  • 引數值
引數 描述
scalewidth 縮放當前繪圖的寬度 (1=100%, 0.5=50%, 2=200%, 依次類推)
scaleheight 縮放當前繪圖的高度 (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

(2)rotate()

  • rotate(angle),圍繞原點旋轉影象angle 弧度。
  • javascript 語法
context.rotate(angle);
  • 引數值
    引數| 描述
    -|-
    angle |旋轉角度,以弧度計。如需將角度轉換為弧度,請使用degreesMath.PI/180 公式進行計算。舉例:如需旋轉 5 度,可規定下面的公式: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

(3)translate()

  • translate(x, y):將座標原點移動到(x,y)。執行這個變換之後,座標(0,0)會變成之前由(x,y)表示的點。
  • javascript語法
context.translate(x,y);
  • 示例
/**繪製一個簡易的時鐘**/
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);
//變換原點
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

(4)transform()

  • 畫布上的每個物件都擁有一個當前的變換矩陣。
  • transform() 方法替換當前的變換矩陣。它以下面描述的矩陣來操作當前的變換矩陣
a  c  e
b  d  f
0  0  1
  • transform() 允許您縮放、旋轉、移動並傾斜當前的環境。
  • javascript語法
context.transform(a,b,c,d,e,f);
  • 引數值
    引數| 描述
    -|-
    a| 水平縮放繪圖
    b| 水平傾斜繪圖
    c| 垂直傾斜繪圖
    d| 垂直縮放繪圖
    e| 水平移動繪圖
    f| 垂直移動繪圖
  • 示例


    矩陣公式
  • 由此可見,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

(5)setTransform()

  • setTransform() 方法把當前的變換矩陣重置為單位矩陣,然後以相同的引數執行 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

2.6 繪製影象

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

/**語法二,在畫布上定點陣圖像,並規定影象的寬度和高度**/
context.drawImage(img,x,y,width,height);

/**語法三,剪下影象,並在畫布上定位被剪下的部分**/
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
  • 引數值
引數 描述
img 規定要使用的影象、畫布或視訊。
sx 可選。開始剪下的 x 座標位置。
sy 可選。開始剪下的 y 座標位置。
swidth 可選。被剪下影象的寬度。
sheight 可選。被剪下影象的高度。
x 在畫布上放置影象的 x 座標位置。
y 在畫布上放置影象的 y 座標位置。
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

2.7 陰影

  • 2D 上下文會根據以下幾個屬性的值,自動為形狀或路徑繪製出陰影。
屬性 描述
shadowColor 用CSS 顏色格式表示的陰影顏色,預設為黑色。
shadowBlur 模糊的畫素數,預設0,即不模糊。
shadowOffsetX 形狀或路徑x 軸方向的陰影偏移量,預設為0。
shadowOffsetY 形狀或路徑y 軸方向的陰影偏移量,預設為0。
  • 示例
var c=document.getElementById("myCanvas");
var context=c.getContext("2d");
//設定陰影
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);
//繪製藍色矩形
context.fillStyle = "rgba(0,0,255,1)";
context.fillRect(30, 30, 50, 50);
陰影

2.8 漸變

  • 漸變由CanvasGradient 例項表示,很容易通過2D 上下文來建立和修改。
    方法| 描述
    -|-
    createLinearGradient()| 建立線性漸變(用在畫布內容上)
    createRadialGradient()| 建立放射狀/環形的漸變(用在畫布內容上)
    addColorStop() |規定漸變物件中的顏色和停止位置

(1)createLinearGradient()

  • createLinearGradient() 方法建立線性的漸變物件。
  • 漸變可用於填充矩形、圓形、線條、文字等等
  • 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() 方法建立放射狀/圓形漸變物件。
  • 漸變可用於填充矩形、圓形、線條、文字等等。
  • 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() 方法在指定的方向內重複指定的元素。
  • 元素可以是圖片、視訊,或者其他 <canvas> 元素。
  • 被重複的元素可用於繪製/填充矩形、圓形或線條等等。
  • 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()

2.10 畫素操作與使用影象資料

  • 2D 上下文 支援畫素操作和使用影象資料
方法 描述
createImageData() 建立新的、空白的 ImageData 物件
getImageData() 返回 ImageData 物件,該物件為畫布上指定的矩形複製畫素資料
putImageData() 把影象資料(從指定的 ImageData 物件)放回畫布上
  • 每個ImageData 物件都有三個屬性:width、height 和data
屬性 描述
width 返回 ImageData 物件的寬度
height 返回 ImageData 物件的高度
data 返回一個物件,其包含指定的 ImageData 物件的影象資料
  • data 屬性是一個陣列,儲存著影象中每一個畫素的資料。對於ImageData物件中的每個畫素,都存在著四方面的資訊,即 RGBA 值:
元素
R 紅色 (0-255)
G 綠色 (0-255)
B 藍色 (0-255)
A alpha 通道 (0-255; 0 是透明的,255 是完全可見的)

(1)createImageData()

  • createImageData() 方法建立新的空白 ImageData 物件。新物件的預設畫素值 transparent black。
  • javascript 語法
/**語法一,以指定的尺寸(以畫素計)建立新的 ImageData 物件**/
var imgData=context.createImageData(width,height);

/**語法二,建立與指定的另一個 ImageData 物件尺寸相同的新 ImageData 物件(不會複製影象資料)**/
var imgData=context.createImageData(imageData);
  • 示例
/**建立 100*100 畫素的 ImageData 物件,其中每個畫素都是綠色的,然後把它放到畫布上**/
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

(2)getImageData()、putImageData()

  • getImageData() 方法返回ImageData物件,該物件拷貝了畫布指定矩形的畫素資料。
  • putImageData() 方法將影象資料(從指定的 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() 來反轉畫布上的影象的每個畫素的顏色**/
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合成

  • 有兩個會應用到2D 上下文中所有繪製操作的屬性:globalAlpha和globalComposition-Operation
屬性 描述
globalAlpha 設定或返回繪圖的當前 alpha 或透明值
globalCompositeOperation 設定或返回新影象如何繪製到已有的影象上

(1)globalAlpha()

  • globalAlpha 屬性設定或返回繪圖的當前透明值(alpha 或 transparency)。

  • globalAlpha 是一個介於0 和1 之間的值(包括0 和1),用於指定所有繪製的透
    明度。預設值為0。

  • javascript 語法

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

(2)globalCompositeOperation()

  • globalCompositeOperation屬性設定或返回如何將一個源(新的)影象繪製到目標(已有)的影象上。
  • 源影象 = 您打算放置到畫布上的繪圖。
  • 目標影象 = 您已經放置在畫布上的繪圖。
  • javascript 語法
context.globalCompositeOperation="source-in";
  • 屬性值
描述
source-over 預設。在目標影象上顯示源影象。
source-atop 在目標影象頂部顯示源影象。源影象位於目標影象之外的部分是不可見的。
source-in 在目標影象中顯示源影象。只有目標影象內的源影象部分會顯示,目標影象是透明的。
source-out 在目標影象之外顯示源影象。只會顯示目標影象之外源影象部分,目標影象是透明的。
destination-over 在源影象上方顯示目標影象。
destination-atop 在源影象頂部顯示目標影象。源影象之外的目標影象部分不會被顯示。
destination-in 在源影象中顯示目標影象。只有源影象內的目標影象部分會被顯示,源影象是透明的。
destination-out 在源影象外顯示目標影象。只有源影象外的目標影象部分會被顯示,源影象是透明的。
lighter 顯示源影象 + 目標影象。
copy 顯示源影象。忽略目標影象。
xor 使用異或操作對源影象與目標影象進行組合。
  • 示例
<!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

2.12 線條樣式

  • 2D 上下文中繪製操作中還具有相應的線條樣式屬性。
    屬性| 描述
    -|-
    lineCap| 設定或返回線條的結束端點樣式
    lineJoin| 設定或返回兩條線相交時,所建立的拐角型別
    lineWidth| 設定或返回當前的線條寬度
    miterLimit| 設定或返回最大斜接長度

(1)lineWidth

  • lineWidth 屬性設定或返回當前線條的寬度,以畫素計。
  • 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

(2)lineCap

  • lineCap 屬性設定或返回線條末端線帽的樣式。
  • javascript 語法
    context.lineCap="butt|round|square";
  • 屬性值
描述
butt 預設。向線條的每個末端新增平直的邊緣。
round 向線條的每個末端新增圓形線帽。
square 向線條的每個末端新增正方形線帽。
  • 示例
//三種不同的線帽
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

(2)lineJoin

  • lineJoin 屬性設定或返回所建立邊角的型別,當兩條線交匯時。
  • javascript語法
context.lineJoin="bevel|round|miter";
  • 屬性值
描述
bevel 建立斜角。
round 建立圓角。
miter 預設。建立尖角
  • 示例
/**當兩條線條交匯時,分別建立斜角、圓形、尖角邊角**/
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

(4)miterLimit

  • miterLimit 屬性設定或返回最大斜接長度。

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


    斜度
  • 只有當 lineJoin 屬性為 "miter" 時,miterLimit 才有效。

  • 邊角的角度越小,斜接長度就會越大。

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

  • 如果斜接長度超過 miterLimit 的值,邊角會以 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

2.13 其它

  • 有兩個方法可以跟蹤上下文的狀態變化。
  • 如果你知道將來還要返回某組屬性與變換的組合,可以呼叫save()方法。呼叫這個方法後,當時的所有設定都會進入一個棧結構,得以妥善保管。
  • 然後可以對上下文進行其他修改。等想要回到之前儲存的設定時,可以呼叫restore()方法,在儲存設定的棧結構中向前返回一級,恢復之前的狀態。
  • 連續呼叫save()可以把更多設定儲存到棧結構中,之後再連續呼叫restore()則可以一級一級返回。
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); //繪製藍色矩形
context.restore();

context.strokeRect(0, 0, 20, 20); //繪製紅色矩形
save()&restore()
5912336-20a19b1af2edb7ec.jpg
好好學習

相關文章