canvas總結(jié)

什么是canvas

HTML5 <canvas> 元素用于圖形的繪制,通過腳本 (通常是JavaScript)來完成.
<canvas> 標(biāo)簽只是圖形容器,您必須使用腳本來繪制圖形。

創(chuàng)建一個(gè)canvas

一個(gè)畫布在網(wǎng)頁中是一個(gè)矩形框,通過 <canvas> 元素來繪制.
注意: 默認(rèn)情況下 <canvas> 元素沒有邊框和內(nèi)容。你也可以添加。

使用如下代碼,你就在頁面中創(chuàng)建出來一個(gè)寬200px、高100px的canvas,如果沒有指定寬高,canvas的默認(rèn)寬高為300px * 150px,通常我們需要給canvas一個(gè)id以便在腳本中引用。

<canvas id="myCanvas" width="200" height="100"></canvas>

我們也可以動(dòng)態(tài)創(chuàng)建canvas,使用一下代碼,我們?cè)陧撁嬷袆?chuàng)建出了一個(gè)id為layer的canvas,指定了其寬高。

var canvas = document.createElement('canvas');
canvas.id = "layer";
canvas.width = 200;
canvas.height = 100;
document.body.appendChild(canvas);

canvas操作

我們可以使用canvas繪制線條、矩形、圓形、文本、圖像,可以對(duì)圖形、文本進(jìn)行顏色填充以及漸變填充。詳細(xì)內(nèi)容可查看基礎(chǔ)教程,其中我們用到的比較多的應(yīng)該是繪制圖像,繪制圖像會(huì)在下面專門講解。

canvas屬性中的寬高和css中寬高的區(qū)別

我們先看一個(gè)例子
我們使用屬性中的寬高創(chuàng)建一個(gè)canvas,其寬高為300px,我們?cè)谄渲挟嬕粭l線,從(0,0)點(diǎn)到(300,300)點(diǎn)。我們可以看出該圖顯示正常不會(huì)被拉伸。

<canvas id="layer" width="300" height="300">瀏覽器不支持Canvas,請(qǐng)升級(jí)或改用其它瀏覽器!</canvas>
<script type="text/javascript">
    var canvas = document.getElementById("layer"),
    ctx = canvas.getContext('2d');
    ctx.moveTo(0,0);
    ctx.lineTo(300,300);
    ctx.stroke();
</script>
屬性寬高

接著我們給canvas設(shè)置一下style中寬高

 #layer {
       width: 150px;
       height: 300px;
}

效果如下,使用style時(shí)圖像會(huì)被拉伸(變形)


設(shè)置style

這是什么原因???我們需要搞清楚兩個(gè)概念:
1.畫布的寬和高(ps新建畫布的寬和高);
2.畫布所在畫板的寬和高(例如ps打開后的窗口);

默認(rèn)的畫板、畫布的寬和高是屬性中設(shè)置的寬高(例子中即為300*300)。但在畫布上設(shè)置style屬性的話,相當(dāng)于把畫板的寬和高改變了,而畫布的寬和高還是默認(rèn)值,所以 畫布會(huì)出現(xiàn)拉伸的情況,此例中設(shè)置的畫板的寬150和高300,相當(dāng)于將畫布的寬度縮小一倍,所以實(shí)際上畫出來的是黑色的那條。 直接設(shè)置寬和高相當(dāng)于是同時(shí)修改了畫板和畫布的寬和高(兩者一致),所以在畫布上畫的圖形不會(huì)出現(xiàn)拉伸(如紅色那條線)。

image.png

canvas繪制圖像

繪制圖像主要使用的是drawImage方法
drawImage() 方法在畫布上繪制圖像、畫布或視頻。
drawImage() 方法也能夠繪制圖像的某些部分,以及/或者增加或減少圖像的尺寸。
語法:
1.在畫布上定義圖像:
context.drawImage(img,x,y);
2.在畫布上定位圖像,并規(guī)定圖像的寬度和高度:
context.drawImage(img,x,y,width,height);
3.剪切圖像,并在畫布上定位被剪切的部分:
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 可選。要使用的圖像的高度。(伸展或縮小圖像)

以上基礎(chǔ)內(nèi)容查看w3c教程

繪制圖像中的填坑

1.繪制圖像時(shí),canvas中沒有圖像

var drawimg = document.getElementById("drawimg");
var image=document.getElementById("image");
var context = drawimg.getContext("2d");
context.drawImage(image,10,10); 

原因是圖片是異步加載,在之前的代碼中,執(zhí)行js代碼的時(shí)候圖片有可能還沒有加載成功,就調(diào)用了drawImage()方法,所以圖片就無法顯示。所以在使用drawImage()方法時(shí),務(wù)必保證所繪圖像已經(jīng)加載好了。通常我們會(huì)將其放在圖片加載onload回調(diào)函數(shù)中確保這一點(diǎn)。

image.onload=function(){
   context.drawImage(devBgImg,imgX,imgY,imgWidth,imgHeight);
};

//例子
var img = new Image();
img.src ='devmonitor/res/main.jpg'; 
img.onload=function(){
ctx.drawImage(img,0,0,img.width,img.height,imgX,imgY,
      canvas.width*imgScale,canvas.height*imgScale);
};

canvas像素操作

語法
context.getImageData(x,y,width,height);

參數(shù) 描述
x 開始復(fù)制的左上角位置的 x 坐標(biāo)。
y 開始復(fù)制的左上角位置的 y 坐標(biāo)。
width 將要復(fù)制的矩形區(qū)域的寬度
height 將要復(fù)制的矩形區(qū)域的高度

getImageData() 方法返回 ImageData 對(duì)象,該對(duì)象拷貝了畫布指定矩形的像素?cái)?shù)據(jù)。

ImageData對(duì)象中存儲(chǔ)著canvas對(duì)象真實(shí)的像素?cái)?shù)據(jù),它包含以下幾個(gè)只讀屬性:

width
無符號(hào)長整型(unsigned long),使用像素描述 ImageData 的實(shí)際寬度。
height
無符號(hào)長整型(unsigned long),使用像素描述 ImageData 的實(shí)際高度。
data
Uint8ClampedArray類型的一維數(shù)組,包含著RGBA格式的整型數(shù)據(jù),范圍在0至255之間(包括255)。

imageData.data;
一維數(shù)組,存儲(chǔ)了從canvas中獲取的每個(gè)像素的RGBA值。該數(shù)組為每個(gè)像素點(diǎn)保存了四個(gè)值——紅、綠、藍(lán)和alpha透明度。
imageData.data并不是一個(gè)真正的數(shù)組,而是一個(gè)類數(shù)組的對(duì)象-------Uint8ClampedArray,data是個(gè)一維數(shù)組!data的元素始終依次是red,green,blue,alpha,red,green,blue。。。一直重復(fù)到最后一個(gè)。所以,data的length始終是像素個(gè)數(shù)*4.而在循環(huán)data的時(shí)候,也是以4為步長。

imageData.data圖示
綜合例子我們可以對(duì)canvas中像素進(jìn)行操作
翻轉(zhuǎn)顏色
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);
// 反轉(zhuǎn)顏色(步長為4)
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);
灰度處理

例子中僅僅是用紅綠和藍(lán)的平均值。你也可以用加權(quán)平均,例如x = 0.299r + 0.587g + 0.114b這個(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);
// 反轉(zhuǎn)顏色(步長為4)
for (var i=0;i<imgData.data.length;i+=4)
  {
      var avg = (data[i] + data[i +1] + data[i +2]) / 3;
      data[i]     = avg; // red
      data[i + 1] = avg; // green
      data[i + 2] = avg; // blue
  }
ctx.putImageData(imgData,0,0);
顏色選擇器:
//創(chuàng)建image對(duì)象
var img = new Image();
img.src = 'haorooms.jpg';
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
//img加載完成后畫到canvas上
img.onload = function() {
  ctx.drawImage(img, 0, 0);
  img.style.display = 'none';
};
//獲取顏色RGBA值的函數(shù)
function pick(event) {
  //layerX和layerY屬性表示Canvas內(nèi)部坐標(biāo)系中的坐標(biāo)
  var x = event.layerX;
  var y = event.layerY;
  var pixel = ctx.getImageData(x, y, 1, 1);
  var data = pixel.data;
  console.log(data);
  //獲取到RGBA值的字符串
  var rgba = 'rgba(' + data[0] + ',' + data[1] +
             ',' + data[2] + ',' + (data[3] / 255) + ')';
  //自定義操作例如將字符串顯示在某dom上或者return返回值等
  //
}
//為canvas綁定mousemove事件
canvas.addEventListener('mousemove', pick);

這篇文章中有對(duì)像素操作的多個(gè)應(yīng)用介紹

canvas和圖片相互轉(zhuǎn)換

//此處image應(yīng)確保加載完成
function convertImageToCanvas(image) {
    var canvas = document.createElement("canvas");
    canvas.width = image.width;
    canvas.height = image.height;
    canvas.getContext("2d").drawImage(image, 0, 0);
    return canvas;
}
// Converts canvas to an image
function convertCanvasToImage(canvas) {
    var image = new Image();
    image.src = canvas.toDataURL("image/png");
    return image;
}

更新中.......
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,310評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,951評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,796評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,566評(píng)論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,055評(píng)論 1 322
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,303評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,799評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,683評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,899評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,135評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,520評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,757評(píng)論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,528評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,844評(píng)論 2 372

推薦閱讀更多精彩內(nèi)容

  • 1 Canvas接口元素定義 1.1 getContext()方法 為了在canvas上繪制,你必須先得到一個(gè)畫布...
    Kevin_Junbaozi閱讀 1,334評(píng)論 1 2
  • 一、簡(jiǎn)介 HTML5 中的定義:“它是依賴分辨率的位圖畫布,你可以在 canvas 上面繪制任何圖形,甚至加載照片...
    destiny0904閱讀 10,564評(píng)論 1 4
  • ??HTML5 添加的最受歡迎的功能就是 元素。這個(gè)元素負(fù)責(zé)在頁面中設(shè)定一個(gè)區(qū)域,然后就可以通過 JavaScri...
    霜天曉閱讀 3,048評(píng)論 0 2
  • 一:canvas簡(jiǎn)介 1.1什么是canvas? ①:canvas是HTML5提供的一種新標(biāo)簽 ②:HTML5 ...
    GreenHand1閱讀 4,702評(píng)論 2 32
  • 一、圖形的組合方式 globalAlpha是一個(gè)介于0和1之間的值(包括0和1),用于指定所有繪制的透明度。默認(rèn)值...
    空谷悠閱讀 1,295評(píng)論 0 0