canvas

canvas

canvas只能在標籤中定義寬高

canvas跟其它標籤一樣,也可以定義樣式,但需要注意的是:canvas的默認寬高爲300px* 150px,在css中爲canvas定義寬高,實際上定義的是canvas的顯示的大小,但針對canvas來說還包括裏面的繪製的圖像的分辨率的大小。所以在css中定義高寬canvas中繪製的圖形可能會變形。因此,我們可以使用以下方式指定大小:

// 在標籤中指定
<canvas class="mycanvas" width="500" height="500">土鱉!你的瀏覽器out啦!</canvas> 
// -->標籤中的內容是當瀏覽器不支持canvas時的後備信息。

// 在js中通過畫布對象屬性的方式指定
var drawing = document.querySelector('.mycanvas');
drawing.width = 500;
drawing.height = 500;

canvas對象的屬性和方法:

  • width;
  • height;
  • getContext(); 獲取canvas對象

canvas中的繪圖是一種基於狀態的繪圖,也就是說我們需要先設置繪圖的狀態,在調用函數做一個具體的繪製。

一、基本用法

要在畫布上繪圖,首先要先獲取繪圖上下文,取得繪圖上下文對象的引用。調用getContext()方法,傳入上下文的名字。如下:

    var drawing = document.querySelector('.mycanvas');

    // 檢測瀏覽器是否支持<canvas>
    if(drawing.getContext) {        
        var context = drawing.getContext('2d'); //獲取繪圖上下文
    }


    if(drawing.getContext('2d')) {} // 不能這樣寫,這樣寫不支持canvas的瀏覽器會報錯!!!

檢測getContext()方法是否存在這一步很有必要。因爲有些瀏覽器會爲HTML規範之外的元素創建默認的HTML元素對象,並且可以引用它,但這個對象並沒有getContext()方法

使用toDataURL()方法,可以導出在< canvas >元素上繪製的圖像。這個參數接受一個參數,即圖像的MIME類型格式,而且適合用於創建圖像的任何上下文。默認情況下,瀏覽器會將圖像編碼爲 PNG 格式(除非另行指定)。Firefox 和 Opera 也支持基於”image/jpeg” 參數的 JPEG 編碼格式。

var drawing = document.querySelector('.mycanvas');

if(drawing.getContext) {
    // 獲取圖像的數據URL
    var imgURL = drawing.toDataURL('image/png');

    // 顯示圖像
    var image = document.createElement('img');
    image.src = imgURL;
    document.body.appendChild(image);
}

如果繪製到畫布上的圖像源自不同的域, toDataURL() 方法會拋出錯誤。

二、2D上下文

1、填充和描邊

  • fillStyle屬性;填充
  • strokeStyle屬性;描邊 屬性值可以使字符串、漸變對象或模式對象。

2、繪製矩形

矩形是唯一一種可以直接在2D上下文中繪製的形狀。

  • fillRect(x, y, width, height); 繪製填充指定顏色的矩形,填充顏色通過fillStyle屬性指定。
  • strokeRect(x, y, width, height); 繪製指定顏色的描邊矩形,描邊顏色通過strokeStyle屬性指定。

    • lineWidth屬性; 線條寬度,值可以是任何整數。
    • lineCap屬性; 控制線條末端的形狀,值可以是:平頭(’butt’)、圓頭(’round’)、方頭(’square’)。
    • lineJoin屬性; 控制線條相交的方式,值可以是:圓交(’round’)、斜交(’bevel’)、斜接(’miter’)。
  • clearRect(x, y, width, height); 清除畫布上的指定區域。

參數單位都是像素。

var drawing = document.querySelector('#mycanvas');
if(drawing.getContext) {
    var context = drawing.getContext('2d');

    context.fillStyle = 'red';
    context.fillRect(10, 10, 100,100);

    context.strokeStyle = 'green';
    context.strokeRect(60, 60, 100, 100);

    context.clearRect(70, 70, 30, 30);
}

3、繪製路徑

創建路徑:
- beginPath(); 開闢新的路徑
- closePath(); 閉合路徑

  • moveTo(x, y);
  • lineTo(x, y); 從上一點開始繪製一條直線,直到(x, y)爲止。

  • rect(x, y, width, height); 繪製矩形路徑

  • arc(x, y, radius, startAngle, endAngle, counterclockwise); 繪製弧線。 (圓心x, 圓心y, 半徑, 開始角度, 結束角度, 是否按逆時針方向計算)

  • arcTo(x1, y1, x2, y2, radius); 繪製弧線
  • bezierCurveTo(c1x, c1y, c2x, c2y, x, y); 貝塞爾曲線。從上一點開始繪製一條曲線,到(x, y)爲止,並且以(c1x, c1y)和(c2x, c2y)爲控制點。
  • quadraticCurveTo(cx, cy, x, y); 從上一點開始繪製一條二次曲線,到(x, y)爲止,並且以(cx, cy)作爲控制點。

繪製圖形:

  • fill(); 填充路徑
  • stroke(); 描邊路徑
  • clip(); 創建一個剪切區域

  • isPointInPath(x, y);用於在路徑被關閉之前確定畫布上的某一點是否位於路徑上

4、繪製文本

  • fillText(str, x, y, maxWidth); 繪製填充文本
  • strokeText(str, x, y, maxWidth); 繪製描邊文本

  • font; 文本樣式、大小及字體

  • textAlign; 文本對齊方式:
    • start 默認。文本在指定的位置開始。
    • end 文本在指定的位置結束。
    • center 文本的中心被放置在指定的位置。
    • left 文本左對齊。
    • right 文本右對齊。
  • textBaseline; 文本的基線:
    • alphabetic 默認。文本基線是普通的字母基線。
    • top 文本基線是 em 方框的頂端。
    • hanging 文本基線是懸掛基線。
    • middle 文本基線是 em 方框的正中。
    • ideographic 文本基線是表意基線。
    • bottom 文本基線是 em 方框的底端。

計算文本大小:

由於繪製文本比較複雜,特別是需要把文本控制在某一區域中的時候,2D上下文提供了輔助確定文本大小的方法measureText(str); 返回TextMetrice對象。返回的對象目前只有一個width屬性,但將來還會增加更多度量屬性。

var fontSize = 100;
context.font = fontSize + 'px Arial';

while(context.measureText('Hello world!').width > 140) {
    fontSize--;
    context.font = fontSize + 'px Arial';
} 
context.fillText('Hello world!', 100, 100);
context.fillText('Font size is ' + fontSize + 'px', 100, 120);

fillText()和strokeText()方法都可以接受第四個參數(maxWidth),也就是文本的最大像素寬度。提供的這個參數後,如果傳入的字符串大於最大寬度,則繪製的文本字符的高度正確,但寬度會收縮以適應最大寬度。不過,這個可選的參數尚未得到所有瀏覽器支持。

5、變換

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

  • rotate(angle); 圍繞原點旋轉。
  • scale(scaleX, scaleY); 縮放圖像,在x方向乘以scaleX,在y方向乘以scaleY。scaleX和scaleY的默認值都是1.0。
  • translate(x, y); 重置原點。
  • transform(m1_1, m1_2, m2_1, m2_2, dx, dy); 修改變換矩陣。
  • setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy); 將變換矩陣重置爲默認狀態,然後在調用transform()。

  • save(); 保存當前上下文狀態。 注意:save()方法保存的只是對繪圖上下文的設置和變換,不會保存繪圖上下文的內容。

  • restore(); 返回上一級保存的上下文狀態。

6、繪製圖像

  • drawImage();

根據期望的最終結果不同,調用這個方法時,可以使用三種不同的參數組合。

1、傳入一個HTML< img >元素,以及繪製該圖像的起點(x,y座標)。如下:

// 取得圖像
var img = document.images[0];
// 將圖像繪製到上下文中
context.drawImage(img, 100, 100);

繪製到畫布上的圖像與原始大小一樣。

2、繪製指定大小的圖像。如果想要改變繪製後的圖像的大小,可以再多穿如兩個參數,分別表示目標寬度和目標高度。通過這種方式來縮放圖像並不影響上下文的變換矩陣。如下:

var img = document.images[0];
context.drawImage(img, 100, 100, 30, 30); // 繪製大小爲30*30的圖像

3、將圖像中的某個區域繪製到上下文中。
drawImage()方法的這種調用方式總共需要出入9個參數:
(img, 源圖像x, 源圖像y, 源圖像width, 源圖像height, 目標圖像x, 目標圖像y, 目標圖像width, 目標圖像height)。

context.drawImage(img, 500, 0, 500, 500, 0, 0, 500, 500);

原始圖像的起點爲(500, 0),寬和高都是500px。最終繪製到上下文中的圖像的起點是(0, 0),而大小變成了500*500px

除了給drawImage()方法傳入HTML< img >元素外,還可以傳入另一個< canvas >元素作爲其第一個參數。這樣就可以把另一個畫布內容會知道當前畫布上。

結合使用drawImage()和其他方法,可以對圖像進行各種基本操作。操作結果可以通過toDataURL()方法獲得。不過,圖像不能來自其他域。如果圖像來自其他域,調用toDataURL()會拋出一個錯誤。例如,位於www.aaa.com上的頁面繪製的圖像來自於www,bbb,com,當前上下文就會被認爲’不乾淨’,因而會拋出錯誤。[注意:toDataURL()是< canvas >對象的方法,而不是上下文對象的方法。]

7、陰影

  • shadowColor; 陰影顏色
  • shadowOffsetX; 形狀或路徑x軸偏移量
  • shadowOffsetY; y軸偏移量
  • shadowBlur; 模糊像素。默認0,即不模糊。

這些屬性都可以通過context對象修改。只要在繪製之前爲它們設置適當的值,就能自動產生陰影。

不同瀏覽器對陰影的支持有一些差異。

8、漸變

  • createLinearGradient(起點x, 起點y, 終點x, 終點y);創建線性漸變。【基於起點的x, y座標以及寬度和高度值創建漸變對象。】
  • createRadialGradient(x1, y1, radius1, x2, y2, radius2);6個參數,分別對應着兩個圓的圓心和半徑。
  • addColorStop(色標位置, CSS顏色值);

漸變有CanvasGradient實例演示,創建一個新的線性漸變,可以調用createLinearGradient()方法。 調用這個方法後,它就會創建一個指定大小的漸變,並返回CanvasGradient對象的實例。創建漸變對象後,下一步就是使用addColorStop()方法來指定色標【色標位置是一個0(開始的顏色)到1(結束的顏色)之間的位數字】。然後把fillStyle或strokeStyle設置爲這個對象,從而使用漸變來繪製或描邊。

// 1、創建漸變對象
var gradient = context.createLinearGradient(110, 110, 310, 310);

// 2、指定色標
gradient.addColorStop(0, 'red');
gradient.addColorStop(0.5, 'yellow');
gradient.addColorStop(1, 'blue');

// 3、將漸變對象賦給fillStyle或strokeStyle
context.fillStyle = gradient;
context.fillRect(110, 110, 200, 200);

createLinearGradient()基於起點的x, y座標以及寬度和高度值創建漸變對象,因此我們可以在fillRect()中使用相同的座標(起點x, 起點y)。如下:

function createLinearGradient(context, x, y, width, height) {
    return context.createLinearGradient(x, y, x + width, y + height);
}

var gradient = createLinearGradient(context, 110, 110, 200, 200);
gradient.addColorStop(0, 'red');
gradient.addColorStop(0.5, 'yellow');
gradient.addColorStop(1, 'blue');


context.fillStyle = gradient;
context.fillRect(110, 110, 200, 200);

徑向漸變: 可以把徑向漸變想象成一個長圓桶,而createRadialGradient()方法的這6個參數定義的就是這個桶的原型開口的位置。

9、模式

模式其實就是重複的圖像,可以用來填充或描邊圖形。
- createPattern(img, str)方法。接收2個參數:一個HTML< img >元素和一個表示如何重複圖像的字符串(與CSS的background-repeat屬性值相同)。

var img = document.images[0];
pattern = context.createPattern(img, 'repeat');

// context.fillStyle = pattern;
// context.fillRect(100, 100, 300, 300);

context.strokeStyle = pattern;
context.lineWidth = 20;
context.strokeRect(100, 100, 300, 300);

模式與漸變一樣,都是從畫布的原點(0, 0)開始的。將填充樣式(fillStyle)設置爲模式對象,只表示在某個特性的區域顯示重複的圖像,而不是要從某個位置開始繪製重複的圖像

10、使用圖像數據

  • getImageData(x, y, width, height); 獲取圖像數據
  • putImageData(x, y, width, height); 回寫圖像數據並顯示結果

2D上下文的一個明顯的長處就是,可以通過getImageData()取得原始圖像數據。這個方法接受4各參數:要取得其數據的畫面區域的x和y座標以及該區域的像素寬度和高度。

var imgData = context.getImageData(10, 5, 50, 50);

這裏返回的對象是ImageData的實例。每個ImageData對象都有三個屬性:width、height和data。其中data屬性是一個數組,保存着圖像總每一個像素的數據。在data數組中,每一個像素用4個元素來保存,分別表示紅、綠、藍和透明度值。因此,第一個像素的數據就保存在數組的第0到第3個元素中。

通過修改圖像數據,可以像下面這樣創建一個簡單的灰階過濾器。如下:

if(drawing.getContext) {
  var context = drawing.getContext('2d');
  var img = document.images[0];
  var imageData, data, i, len, average, red, green, blue, alpha;

  // 繪製原始圖像
  context.drawImage(img, 0, 0);

  // 取得圖像數據
  imageData = context.getImageData(0, 0, img.width, img.height);
  data = imageData.data;
  for(i = 0,len = data.length; i < len; i+=4) {
    red = data[i];
    green = data[i+1];
    blue = data[i+2];
    alpha = data[i+3];
    // 求得rgb平均值
    average = Math.floor((red + green + blue) /3 + 10);

    // 設置顏色值,透明度不變
    data[i] = average;
    data[i+1] = average;
    data[i+2] = average;
  }
  // 回寫圖像數據並顯示結果
  imageData.data = data;
  context.putImageData(imageData, 0, 0);
}

通過操作原始像素值不僅能實現灰階過濾,還能實現其他功能。

11、合成

  • globalAlpha; 指定所有繪製的透明度。(值介於0~1之間,包括0和1)
  • globalCompositionOperation; 表示後繪製的圖形怎樣與先繪製的圖形結合。
    可能的字符串值:
  • source-over(默認值); 後繪製的圖形位於先繪製的圖形上方。
  • source-in; 後繪製的圖形與之前的圖形重疊的部分可見
  • source-out; 後繪製的圖形與之前的圖形不重疊的部分可見
  • source-atop; 後繪製的圖形與之前的圖形重疊的部分可見,但先繪製的圖形不受影響
  • destination-over; 後繪製的圖形位於先繪製的圖形下方。
  • destination-in;
  • destination-out;
  • destination-atop; 後繪製的圖形位於先繪製的圖形的下方,在兩者不重疊的地方,先繪製的圖形變透明
  • lighter; 後繪製的圖形與先繪製的圖形重疊部分的值相加,使該部分變亮。
  • copy; 後繪製的圖形完全替代與之重疊
  • 的先繪製圖形。
  • xor; 後繪製的圖形與先繪製的圖形重疊的部分執行“異步”操作。

三、WebGL

WebGL是針對Canvas的3D上下文。與其他Web技術不同,WebGL並不是W3C制定的標準,而是有Khronos Group制定的。
Khtonos Group也設計了其他圖形處理API,比如OpenGL ES 2.0。

…此處省略…

四、context繪圖上下文對象的canvas屬性

canvas屬性; 返回當前繪圖上下文對象所屬的canvas對象

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章