Canvas API總結

概述

Canvas(畫布)用於在網頁實時生成圖像,而且能夠操做圖像內容,基本上它是一個能夠用JavaScript操做的位圖(bitmap)。css

開始使用


  1. 新建一個<canvas>網頁元素。
<canvas id="myCanvas" width="400" height="200">
你的瀏覽器不支持canvas!
</canvas>
複製代碼
  • 替換內容
    • 支持<canvas>的瀏覽器將會忽略在容器中包含的內容,正常渲染canvas。
    • 不支持<canvas>的瀏覽器會顯示代替內容
  • widthheight
    • 默認寬度爲300像素,默認高度爲150像素。
    • html屬性設置width/height時隻影響畫布自己不影畫布內容
    • css屬性設置width/height時不但會影響畫布自己的高寬,還會使畫布中的內容等比例縮放(縮放參照於畫布默認的尺寸)
  1. <canvas>元素只是創造了一個固定大小的畫布,要想在它上面去繪製內容,須要用getContext()方法找到它的渲染上下文
//獲取canvas容器
var canvas = document.getElementById('myCanvas');
//建立一個渲染上下文
if (canvas.getContext) {
  var ctx = canvas.getContext('2d');
}
複製代碼

上面代碼中,getContext方法指定參數2d,表示該canvas節點用於生成2D圖案(即平面圖案)。若是參數是webgl,就表示用於生成3D圖像(即立體圖案),這部分實際上單獨叫作WebGL API。html

繪圖方法

canvas畫布提供了一個用來做圖的平面空間,該空間的每一個點都有本身的座標,x表示橫座標,y表示豎座標。原點(0, 0)位於圖像左上角,x軸的正向是原點向右,y軸的正向是原點向下前端

樣式和顏色

  • fillStyle :設置填充顏色,默認黑色
  • strokeStyle :設置輪廓顏色,默認黑色
  • lineWidth :設置線條寬度,屬性值爲任意正整數,默認值是1.0。
  • lineJoin:控制線條相交的方式(默認是miter
    • round : 圓角
    • bevel : 斜角
    • miter : 直角
  • lineCap:線段末端的形狀(默認值是 butt)
    • butt :線段末端以方形結束。
    • round :線段末端以圓形結束
    • square:線段末端以方形結束,可是增長了一個寬度和線段相同,高度是線段厚度一半的矩形區域

save()、restore()、beginPath()

  • 樣式容器
    • 每次調用樣式api時,都會往樣式容器裏作登記
    • 調用save()時,將樣式容器中的狀態壓棧,保存上下文環境
    • 調用restore()時,將樣式棧的棧頂狀態彈出到樣式容器中,恢復到上一次保存的上下文環境
//用save方法,保存了當前設置
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);

//使用restore方法,恢復了保存前的設置
ctx.restore();

//繪製了一個沒有陰影的矩形
ctx.fillStyle = '#000000';
ctx.fillRect(180,10,150,100);
複製代碼
  • 路徑容器
    • 每次調用路徑api時,都會往路徑容器裏作登記
    • 調用beginPath時,清空整個路徑容器
ctx.save();
//關於樣式的設置
ctx.beginPath();
//關於路徑的設置
ctx.restore();
複製代碼

變換

  • translate(x, y):將canvas座標原點移動到(x,y),translate是累加
  • rotate(angle):圍繞原點旋轉圖像angle弧度(順時針),rotate是累加
  • scale(x, y):縮放圖像;x和y分別是橫軸和縱軸的縮放因子(正值),scale是累加
    • 比 1.0 小:縮小
    • 比 1.0 大:放大
    • 爲 1.0 時什麼效果都沒有

(1)繪製矩形

//填充矩形(x, y是橫縱座標,原點在canvas的左上角)
ctx.fillRect(x, y, width, height);
//邊框矩形,默認1px 黑色。   
ctx.strokeRect(x, y, width, height);
//清除指定的矩形區域,變爲透明
ctx.clearRect(x, y, width, height);       //繪製動態效果時,經常使用來清除整個畫布
複製代碼
  • rect(x, y, width, height):繪製矩形路徑

(2)繪製路徑

//新建路徑,beginPath是繪製新圖形的開始
ctx.beginPath()
//路徑(線)的起點,通常在上面這條命令後執行
ctx.moveTo(x, y)  
//線的終點
ctx.lineTo(x, y)   
//閉合路徑,不是必須的,若是線的終點跟起點同樣,會自動閉合。
ctx.closePath()
//經過線條繪製輪廓(邊框)
ctx.stroke() //不會自動調用closePath()  
//經過路徑填充區域(實心)
ctx.fill()  //自動調用closePath()
複製代碼

例:繪製一個三角形web

ctx.beginPath();
ctx.moveTo(75, 50);    //路徑起點
ctx.lineTo(100, 75);
ctx.lineTo(100, 25);
ctx.fill();   //自動將路徑閉合,並默認填充黑色。
複製代碼
  • quadraticCurveTo(cp1x, cp1y, x, y):繪製二次貝塞爾曲線,cp1x,cp1y爲一個控制點,起始點爲moveto時指定的點,x,y爲結束點。
  • bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y):繪製三次貝塞爾曲線,cp1x,cp1y爲控制點一,cp2x,cp2y爲控制點二,起始點爲moveto時指定的點,x,y爲結束點。
  • ctx.isPointInPath(x, y):判斷在當前路徑中是否包含檢測點
    • x:檢測點的X座標
    • y:檢測點的Y座標
    • 注意,此方法只做用於最新畫出的canvas圖像

(3)繪製文本

  • fillText(string, x, y):在指定的(x,y)位置填充指定的文本
    • 4個參數:文本字符串、起點的x座標、y座標、可選的最大像素寬度。
  • strokeText(string, x, y):在指定的(x,y)位置填充指定的文本
// 設置字體,必需要有大小和字體
ctx.font = "Bold 20px Arial"; 
// 設置對齊方式,可選值包括: left, right  center
ctx.textAlign = "left";
// 設置填充顏色
ctx.fillStyle = "#008600"; 
// 設置字體內容,以及在畫布上的位置
ctx.fillText("Hello!", 10, 50); 
// 繪製空心字
ctx.strokeText("Hello!", 10, 100); 
複製代碼
  • measureText() 方法:返回一個TextMetrics 對象,包含關於文本尺寸的信息(例如文本的寬度)

(4)繪製圓形和扇形

//繪製圓形
ctx.arc(x, y, r, start, end, true/false)   //(x, y)圓心,r半徑,start和end是開始和結束角度,false表示順時針(默認),true表示逆時針。
//繪製弧線
ctx.arcTo(x1, y1, x2, y2, r);    //當前端點、(x1,y1)和(x2,y2)這三個點連成的弧線,r是半徑。
複製代碼

例:繪製實心的圓形算法

ctx.beginPath(); 
ctx.arc(60, 60, 50, 0, Math.PI*2, true); 
ctx.fillStyle = "#000000"; 
ctx.fill();
複製代碼

例:繪製空心圓形canvas

ctx.beginPath(); 
ctx.arc(60, 60, 50, 0, Math.PI*2, true); 
ctx.lineWidth = 1.0; 
ctx.strokeStyle = "#000"; 
ctx.stroke();
複製代碼

(5)設置陰影

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

ctx.fillStyle = "#CC0000"; 
ctx.fillRect(10,10,200,100);
複製代碼

(6)設置漸變

  • createLinearGradient(x1, y1, x2, y2):建立一個canvas漸變(線性漸變)
    • 漸變起點 (x1,y1) 與終點 (x2,y2)
  • gradient.addColorStop(position, color)
    • gradient:createLinearGradient的返回值
    • addColorStop 方法接受 2 個參數:
      • position 參數必須是一個 0.0 與 1.0 之間的數值,表示漸變中顏色所在的相對位置,例如,0.5 表示顏色會出如今正中間。
      • color 參數必須是一個有效的 CSS 顏色值,如 #FFF, rgba(0,0,0,1)等等
//建立一個canvas線性漸變,返回`CanvasGradient`對象的實例
var myGradient = ctx.createLinearGradient(0, 0, 0, 160); 

myGradient.addColorStop(0, "#BABABA"); 

myGradient.addColorStop(1, "#636363");
//繪製漸變填充的矩形
ctx.fillStyle = myGradient;
ctx.fillRect(10,10,200,100);
複製代碼
  • createRadialGradient(x1, y1, r1, x2, y2, r2):canvas漸變(徑向漸變)
    • 前三個參數則定義另外一個以(x1,y1) 爲原點,半徑爲 r1 的圓
    • 後三個參數則定義另外一個以 (x2,y2) 爲原點,半徑爲 r2 的圓

圖像處理方法

drawImage()方法

Canvas API 容許將圖像文件插入畫布,作法是讀取圖片後,使用drawImage方法在畫布內進行重繪。api

  • canvas操做圖片時,必需要等圖片加載完才能操做
  • drawImage(image, x, y, width, height)
    • image:圖像文件的DOM元素
    • xy :繪製該圖像的起始座標
    • widthheight:目標寬高
var image = new Image();
image.src = 'image.png';

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;
}


複製代碼

createPattern()方法:設置背景模式

  • createPattern(image, repetition)
    • image:圖像源
    • epetition
      • repeat
      • repeat-x
      • repeat-y
      • no-repeat

通常狀況下,咱們都會將fillstyle的值設置爲createPattern返回的對象,只表示在某個特定的區域內顯示重複的圖像。數組

getImageData()方法,putImageData()方法

經過getImageData方法和putImageData方法,能夠處理每一個像素,進而操做圖像內容。瀏覽器

  • ctx.getImageData(sx, sy, sw, sh):得到一個包含畫布場景像素數據的ImageData對象,它表明了畫布區域的對象數據
    • 參數
      • sx:要被提取的畫面區域的 x 座標。
      • sy:要被提取的畫面區域的 y 座標。
      • sw:要被提取的像素寬度。
      • sh:要被提取的像素高度。
    • ImageData對象中存儲着canvas對象真實的像素數據,它包含如下幾個只讀屬性:
      • width:圖片寬度,單位是像素
      • height:圖片高度,單位是像素
      • data:Uint8ClampedArray類型的一維數組, 包含着RGBA格式的整型數據,範圍在0至255之間(包括255)
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
複製代碼
  • putImageData(myImageData, dx, dy):把圖像數據繪製到畫布上
context.putImageData(imageData, 0, 0);
複製代碼
  • 套路代碼

假定filter是一個處理像素的函數,那麼整個對Canvas的處理流程,能夠用下面的代碼表示。bash

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

    context.putImageData(imageData, 0, 0);

}
複製代碼

createImageData()方法

  • ctx.createImageData(width, height):建立一個ImageData對象
    • width : ImageData 新對象的寬度。
    • height: ImageData 新對象的高度。
    • 默認建立出來的是透明的

合成

  • globalAlpha = value:設置全局透明度,這個屬性影響到 canvas 裏全部圖形的透明度
    • 有效的值範圍是 0.0 (徹底透明)到 1.0(徹底不透明)
    • 默認是 1.0
  • globalCompositeOperation:覆蓋合成(source--->新的圖像(源);destination--->已經繪製過的圖形(目標))
    • source-over(默認值):源在上面,新的圖像層級比較高
    • source-in :只留下源與目標的重疊部分(源的那一部分)
    • source-out :只留下源超過目標的部分
    • source-atop:砍掉源溢出的部分
    • destination-over:目標在上面,舊的圖像層級比較高
    • destination-in:只留下源與目標的重疊部分(目標的那一部分)
    • destination-out:只留下目標超過源的部分
    • destination-atop:砍掉目標溢出的部分

toDataURL():將畫布導出爲圖像

注意是canvas元素接口上的方法

function convertCanvasToImage(canvas) {
  var image = new Image();
  image.src = canvas.toDataURL('image/png');
  return image;
}
複製代碼

上面的代碼將Canvas數據,轉化成PNG data URI。

常見效果

灰度效果

灰度圖(grayscale)就是取紅、綠、藍三個像素值的算術平均值。假定d[i]是像素數組中一個象素的紅色值,則d[i+1]爲綠色值,d[i+2]爲藍色值,d[i+3]就是alpha通道值。轉成灰度的算法,就是將紅、綠、藍三個值相加後除以3,再將結果寫回數組。

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;

};
複製代碼

復古效果

復古效果(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;

};
複製代碼
相關文章
相關標籤/搜索