canvas

@(HTML5)[canvas與SVG]

[TOC]

十 、canvas

canvas的基本用法

canvas是HTML5中的新的標(biāo)簽,表示一個HTML畫布對象梧躺。

定義canvas元素

<canvas id="canvas" width="500" height="500">對不起奥吩,你的瀏覽器不支持canvas標(biāo)簽</canvas>

canvas只有兩個屬性(width與height)。默認(rèn)的width是300px构拳,高度是150px咆爽。注意:不要使用css樣式指定canvas的大小。

渲染上下文

canvas初始化是空白的置森,要在上面用腳本畫圖首先需要其渲染上下文斗埂,可以通過canvas對象的getContext方法來獲取,同時得到的還有一些畫圖用的函數(shù)凫海。

這里來看看一個例子:

function draw() {
      var canvas = document.getElementById("canvas");
      if (canvas.getContext) {
        var ctx = canvas.getContext("2d");
        ctx.fillStyle = "rgb(200,0,0)";
        ctx.fillRect (10, 10, 55, 50);
        ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
        ctx.fillRect (30, 30, 55, 50);
      }
    }

canvas繪制圖形

我們先來看一下canvas的網(wǎng)格
在上面的例子中繪制了兩個正方形呛凶,拿其中的紅色正方形來講。運行代碼后行贪,會發(fā)現(xiàn)它離左上角有一定的距離漾稀。這個距離是由傳進(jìn)的參數(shù)來決定的,是(10,10)建瘫。這表示這個正方形的原點的坐標(biāo)崭捍。在canvas網(wǎng)格中,原點定在左上角的位置(坐標(biāo)(0,0))啰脚。所有canvas里所繪制的圖形的位置都是相對這個原點的殷蛇。看下圖,這個藍(lán)色的方塊的位置就是距離左邊x像素粒梦,距離上邊y像素亮航,即它的坐標(biāo)是(x,y)。實際上匀们,是(x-0,y-0)缴淋,由于canvas定原點坐標(biāo)為(0,0)所以便是(x,y)。


enter image description here

下面我們來看看繪制的具體的方法

繪制矩形

以下單個函數(shù)是繪制矩形:

fillRect(x,y,width,height) //填充一個矩形
strokeRect(x,y,width,height) //繪制一個矩形的邊框(但不填充矩形的內(nèi)部)
clearRect(x,y,width,height) //擦出了指定的矩形泄朴,并且用一個透明的顏色填充

繪制路徑

與繪制路徑有關(guān)的函數(shù):

beginPath()  //丟棄任何當(dāng)前定義的路徑并且開始一條新的路徑宴猾。它把當(dāng)前的點設(shè)置為(0,0)。當(dāng)一個畫布的環(huán)境第一次創(chuàng)建時叼旋,beginPath()方法會被顯示地調(diào)用仇哆。
closePath()  //創(chuàng)建從當(dāng)前點到開始點的路徑。
stroke()  //方法繪制當(dāng)前路徑的邊框夫植。它意味著畫輪廓讹剔,但是線條的可視化取決于strokeStyle、lineWidth详民、lineJoin延欠、lineCap和miterLimit等屬性。
fill()  //方法用于填充路徑沈跨,默認(rèn)是黑色由捎。fill()方法使用fillStyle屬性所指定的顏色、漸變和模式來填充當(dāng)前路徑饿凛。當(dāng)調(diào)用該方法時狞玛,開放的路徑會自動閉合。

moveTo()方法

moveTo(x,y) //用于定位繪畫的位置涧窒,即將點移動到參數(shù)x,y所指定的坐標(biāo)位置心肪。

canvas初始化或者調(diào)用了beginPath()方法時,繪畫開始的位置即原點(0,0)纠吴,使用moveTo()方法硬鞍,我們可以將起始位置移動到任何我們想要的地方。

lineTo()方法

lineTo(x,y) //接受終點的坐標(biāo)(x,y)作為參數(shù)戴已。起始坐標(biāo)取決于前一路徑的終點坐標(biāo)固该。當(dāng)然,起始坐標(biāo)也可以通過前面介紹的moveTo()方法來設(shè)置糖儡。

arc()方法

arc(x, y, radius, startAngle, endAngle, anticlockwise)

該方法接受6個參數(shù)伐坏。其中,x,y是圓心坐標(biāo)休玩;radius是圓的半徑著淆;startAngle和endAngle分別是起末弧度(以x軸為基準(zhǔn));anticlockwise為true表示逆時針拴疤,反之為順時針永部。
這邊有一點是需要注意的,就是arc方法里的角度是以弧度為計算單位的呐矾,不是度苔埋。這么說吧,通常我們說的180度蜒犯,就等價于PI组橄。兩者的計算公式是這樣的:radians=(Math.PI/180)*degrees.(其中,radians代表弧度罚随,degrees代表度)

貝塞爾與二次方曲線

貝塞爾曲線(Bézier curve)玉工,又稱貝茲曲線或貝濟埃曲線,是應(yīng)用于二維圖形應(yīng)用程序的數(shù)學(xué)曲線

二次貝塞爾曲線

quadraticCurveTo(cpx, cpy, x, y)

其中淘菩,cpx指控制點的x坐標(biāo)遵班;cpy指控制點的y坐標(biāo);x指結(jié)束點的x坐標(biāo)潮改;y指結(jié)束點的y坐標(biāo)狭郑。

看看下面的這個圖片:

enter image description here

由上面的參數(shù)可以看出,二次貝賽爾曲線需要兩個點:第一個點用于二次貝賽爾計算中的控制點汇在,第二個點是曲線的結(jié)束點翰萨。曲線的開始點是當(dāng)前路徑中最后一個點。如果路徑不存在糕殉,可使用beginPath()和moveTo()方法來定義亩鬼。

三次貝塞爾曲線

bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

其中,cp1x為第一個控制點的x坐標(biāo)阿蝶;cp1y為第一個控制點的y坐標(biāo)辛孵;cp2x為第二個控制點的x坐標(biāo);cp2y為第二個控制點的y坐標(biāo)赡磅;x為結(jié)束點的x坐標(biāo)魄缚;y為結(jié)束點的y坐標(biāo)。

再來看一張圖片:


enter image description here

由上面可以看出焚廊,三次貝賽爾曲線需要三個點冶匹。前兩個點用于三次貝賽爾計算中的控制點,第三個點是曲線結(jié)束的控制點咆瘟。同上嚼隘,曲線的開始點是當(dāng)前路徑中最后一個點。如果路徑不存在袒餐,可使用beginPath()和moveTo()方法來定義飞蛹。

canvas運用樣式與顏色

色彩

fillStyle=color;
strokeStyle=color;

fillStyle用于設(shè)置填充的顏色谤狡,而strokeStyle用于設(shè)置圖像輪廓的顏色。color可以是表示css顏色值的字符串卧檐、漸變對象或者圖案對象墓懂。默認(rèn)情況下,線條顏色和填充顏色都是黑色的霉囚。

透明度

globalAlpha

globalAlpha = transparencyValue

這個屬性會影響canvas里所有在設(shè)置透明度后繪制的圖形的透明度捕仔。它的取值區(qū)間是[0.0,1.0]。其中盈罐,0.0表示完全透明榜跌,1.0表示完全不透明。默認(rèn)值是1.0盅粪。

rgba

由于strokeStyle和fillStyle都接受符合css3規(guī)范的顏色值钓葫,所以還可以使用另一種設(shè)置透明度的方法,那就是rgba()方法票顾,它的靈活性更大瓤逼。

線型

lineWidth屬性

lineWidth用于設(shè)置當(dāng)前繪制的線的粗細(xì)。屬性值必須為正數(shù)库物。默認(rèn)值為1.0霸旗。
注意,這里的線寬是指給定路徑的中心到兩邊的粗細(xì)戚揭。換句話說就是:在路徑的兩邊各繪制線寬的一半诱告。

enter image description here

lineCap屬性

屬性lineGap設(shè)置或返回了線條末端線帽的樣式。

它有三個可選值民晒,分別為:butt精居,這個值是默認(rèn)的,表示向線條的每個末端添加平直的邊緣潜必;round靴姿,表示向線條的每個末端添加圓形線帽;square磁滚,表示向線條的每個末端添加正方形的線帽佛吓。

enter image description here

lineJoin屬性

當(dāng)一個路徑包含了線段或曲線相交的交點時,lineJoin屬性說明如何繪制這些交點垂攘。只有當(dāng)繪制具有等寬線條的時候维雇,這一屬性的效果才能表現(xiàn)出來。

它的可選值有三個晒他,分別是:round吱型、bevelmiter。默認(rèn)值是miter陨仅。
下圖從上往下的三個小圓:

enter image description here

miterLimit屬性

miterLimit 屬性設(shè)置或返回最大斜接長度津滞。
斜接長度指的是在兩條線交匯處內(nèi)角和外角之間的距離铝侵。


enter image description here

注意:只有當(dāng) lineJoin 屬性為 “miter” 時,miterLimit 才有效触徐。

邊角的角度越小咪鲜,斜接長度就會越大。為了避免斜接長度過長锌介,我們可以使用 miterLimit 屬性。

如果斜接長度超過 miterLimit 的值猾警,邊角會以 lineJoin 的 “bevel” 類型來顯示(圖解 3):


enter image description here

語法:

miterLimit=number;

使用虛線

setLineDash 方法和lineDashOffset屬性來制定虛線樣式. setLineDash 方法接受一個數(shù)組孔祸,來指定線段與間隙的交替;lineDashOffset 屬性設(shè)置起始偏移量.

setLineDash([5, 15])

一個跑馬燈的例子:

var ctx = document.getElementById('canvas').getContext('2d');
var offset = 0;

function draw() {
  ctx.clearRect(0,0, canvas.width, canvas.height);
  ctx.setLineDash([4, 2]);
  ctx.lineDashOffset = -offset;
  ctx.strokeRect(10,10, 100, 100);
}

function march() {
  offset++;
  if (offset > 16) {
    offset = 0;
  }
  draw();
  setTimeout(march, 20);
}

march();

漸變

線性漸變

createLinearGradient(xStart, yStart, xEnd, yEnd)

線性漸變有四個參數(shù)发皿,其中xStart,yStart為漸變起始點的坐標(biāo)崔慧;xEnd,yEnd為漸變結(jié)束點的坐標(biāo)。

徑向漸變

createRadialGradient(xStart, yStart, radiusStart, xEnd, yEnd, radiusEnd)

徑向漸變有六個參數(shù)穴墅,其中xStart,yStart為開始圓的圓心坐標(biāo)惶室;radiusStart為開始圓的半徑;xEnd, yEnd為結(jié)束圓的圓心坐標(biāo)玄货;radiusEnd為結(jié)束圓的半徑皇钞。

注意,以上兩個方法都沒有為漸變指定任何顏色松捉。使用返回對象的addColorStop()來設(shè)置顏色夹界。要使用一個漸變來勾勒線條或填充區(qū)域,只需要把CanvasGradient對象賦給strokeStyle屬性或fillStyle屬性即可隘世。

addColorStop

addColorStop(offset,color)

offset是一個范圍在0.0到1.0之間的浮點值可柿,表示漸變開始點和結(jié)束點直接的一部分。offset值為0對應(yīng)開始點丙者,offset值為1對應(yīng)結(jié)束點复斥。

使用createPattern創(chuàng)建重復(fù)圖片

語法:createPattern(image, type)
image是圖片,type是圖片的重復(fù)(repeat械媒,repeat-x目锭,repeat-y 和 no-repeat)
創(chuàng)建出一個 pattern 之后,賦給 fillStyle 或 strokeStyle 屬性即可纷捞。
例如:

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');

  // 創(chuàng)建新 image 對象侣集,用作圖案
  var img = new Image();
  img.src = 'images/wallpaper.png';
  img.onload = function(){

    // 創(chuàng)建圖案
    var ptrn = ctx.createPattern(img,'repeat');
    ctx.fillStyle = ptrn;
    ctx.fillRect(0,0,150,150);

  }
}

canvas填充規(guī)則

當(dāng)我們用到 fill(或者 clip和isPointinPath )你可以選擇一個填充規(guī)則,該填充規(guī)則根據(jù)某處在路徑的外面或者里面來決定該處是否被填充兰绣,這對于自己與自己路徑相交或者路徑被嵌套的時候是有用的世分。
兩個可能值:nonzero(默認(rèn),一般沒用) evenodd

繪制文本

兩種繪制方式

fillText(text,x,y[,maxWidth])
在指定的(x,y)位置填充指定的文本缀辩,繪制的最大寬度是可選的.
strokeText(text, x, y [, maxWidth])
在指定的(x,y)位置繪制文本邊框臭埋,繪制的最大寬度是可選的.

有樣式的文本

font
當(dāng)前我們用來繪制文本的樣式. 這個字符串使用和 CSS font 屬性相同的語法. 默認(rèn)的字體是 10px sans-serif踪央。
textAlign
文本對齊選項. 可選的值包括:start, end, left, right or center. 默認(rèn)值是 start。
textBaseline
基線對齊選項. 可選的值包括:top, hanging, middle, alphabetic, ideographic, bottom瓢阴。默認(rèn)值是 alphabetic畅蹂。
direction:ltr,rtl

文本測量

measureText()方法

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  var text = ctx.measureText("foo"); // TextMetrics object
  text.width; // 16;
}

陰影

shadowOffsetX
shadowOffsetY
shadowBlur
shadowColor

canvas應(yīng)用圖像

可以使用的圖片源

  • HTMLImageElemment:這些圖片是由Image()函數(shù)構(gòu)造出來的,或者任何的<img>元素
  • HTMLVideoElement:用一個HTML的 <video>元素作為你的圖片源荣恐,可以從視頻中抓取當(dāng)前幀作為一個圖像
  • HTMLCanvasElement:可以使用另一個 <canvas>元素作為你的圖片源液斜。
  • ImageBitmap:這是一個高性能的位圖,可以低延遲地繪制叠穆,它可以從上述的所有源以及其它幾種源中生成少漆。

drawImage

drawImage方法有三種狀態(tài)`,下面為最簡單的一種硼被。

第一種

drawImage(img,x,y);

其中示损,img規(guī)定要使用的圖像、畫布或視頻嚷硫;x指在畫布上放置圖像的x坐標(biāo)位置检访;y指在畫布上放置的圖像的y坐標(biāo)位置。
注意:引用圖片可是使用js的new Image()來創(chuàng)建仔掸。這個方法的缺點是脆贵,腳本會因為等待圖片加載而暫停∑鹉海可以使用onload事件丹禀,等圖片加載完再執(zhí)行相應(yīng)的代碼。

例如:

var img = new Image();   // Create new Image object
img.onload = function(){
  // 執(zhí)行drawImage語句
}
img.src = 'myImage.png'; // Set source path

第二種:縮放圖片

drawImage(img,x,y,width,height);

img,x,y三個參數(shù)和上面一致鞋怀,新增的兩個參數(shù)分別表示:width双泪,在canvas中圖片要顯示的寬度;height密似,在canvas中圖片要顯示的高度焙矛。

第三種:剪切圖片

drawImage(img,sx,sy,swidth,sheight,x,y,width,height);

它一共有九個參數(shù),分別為:img残腌,源圖片對象村斟;sx,開始剪切的x坐標(biāo)位置抛猫;sy蟆盹,開始剪切的y坐標(biāo)位置;swidth闺金,要剪切的寬度逾滥;sheight,要剪切的高度败匹;x寨昙,剪切后在畫布顯示的x坐標(biāo)位置讥巡;y,剪切后舔哪,在畫布上顯示的y坐標(biāo)的位置欢顷;width,剪切后要顯示的圖片的寬度捉蚤;height抬驴,剪切后要顯示的圖片的高度。

變形 transform

translate(x,y)
rotate(angle)
scale(x,y)

狀態(tài)的保存與恢復(fù)

save()與restore()
save 和 restore 方法是用來保存和恢復(fù) canvas 狀態(tài)的缆巧,都沒有參數(shù)布持。Canvas 的狀態(tài)就是當(dāng)前畫面應(yīng)用的所有樣式和變形的一個快照。
執(zhí)行的步驟:
Canvas狀態(tài)存儲在棧中盅蝗,每當(dāng)save()方法被調(diào)用后鳖链,當(dāng)前的狀態(tài)就被推送到棧中保存姆蘸。一個繪畫狀態(tài)包括:

當(dāng)前應(yīng)用的變形(即移動墩莫,旋轉(zhuǎn)和縮放,見下)
strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation 的值
當(dāng)前的裁切路徑(clipping path)逞敷,會在下一節(jié)介紹  

每一次調(diào)用 restore 方法狂秦,上一個保存的狀態(tài)就從棧中彈出,所有設(shè)定都恢復(fù)推捐。
典型的例子就是canvas繪制時鐘

使用clip()裁切路徑

除了之前的stroke與fill裂问,還有一個是clip(),用法語其他兩個一樣牛柒,只是這個是用來裁切的堪簿。注意:裁剪區(qū)域必須放在繪制區(qū)域上面

    c.arc(0,0,60,0,Math.PI*2,true);
    c.fill();
    c.clip();
    c.fillStyle = "red";
    c.fillRect(0,0,150,150);

canvas動畫

動畫的基本步驟

  1. 清空canvas
  2. 保存canvas狀態(tài)
  3. 重繪動畫
  4. 恢復(fù)canvas

操控動畫

使用
window.setTnterval(function,delay)
window.setTimeote(function,delay)
一般是使用下面這個
window.requestAnimationFrame(callback)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末皮壁,一起剝皮案震驚了整個濱河市椭更,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蛾魄,老刑警劉巖虑瀑,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異滴须,居然都是意外死亡舌狗,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進(jìn)店門扔水,熙熙樓的掌柜王于貴愁眉苦臉地迎上來痛侍,“玉大人,你說我怎么就攤上這事魔市×等眨” “怎么了膀篮?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵,是天一觀的道長岂膳。 經(jīng)常有香客問我誓竿,道長,這世上最難降的妖魔是什么谈截? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任筷屡,我火速辦了婚禮,結(jié)果婚禮上簸喂,老公的妹妹穿的比我還像新娘毙死。我一直安慰自己,他們只是感情好喻鳄,可當(dāng)我...
    茶點故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布扼倘。 她就那樣靜靜地躺著,像睡著了一般除呵。 火紅的嫁衣襯著肌膚如雪再菊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天颜曾,我揣著相機與錄音纠拔,去河邊找鬼。 笑死泛豪,一個胖子當(dāng)著我的面吹牛稠诲,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播诡曙,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼臀叙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了价卤?” 一聲冷哼從身側(cè)響起劝萤,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎荠雕,沒想到半個月后稳其,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡炸卑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年既鞠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盖文。...
    茶點故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡嘱蛋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情洒敏,我是刑警寧澤龄恋,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站凶伙,受9級特大地震影響郭毕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜函荣,卻給世界環(huán)境...
    茶點故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一显押、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧傻挂,春花似錦乘碑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绪抛,卻和暖如春资铡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背睦疫。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工害驹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鞭呕,地道東北人蛤育。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像葫松,于是被迫代替她去往敵國和親瓦糕。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,922評論 2 361

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

  • 一:canvas簡介 1.1什么是canvas腋么? ①:canvas是HTML5提供的一種新標(biāo)簽 ②:HTML5 ...
    GreenHand1閱讀 4,693評論 2 32
  • 1 Canvas接口元素定義 1.1 getContext()方法 為了在canvas上繪制咕娄,你必須先得到一個畫布...
    Kevin_Junbaozi閱讀 1,315評論 1 2
  • 一、canvas簡介 1.1 什么是canvas珊擂?(了解) 是HTML5提供的一種新標(biāo)簽 Canvas是一個矩形區(qū)...
    Looog閱讀 3,942評論 3 40
  • 一圣勒、canvas簡介 1.1 什么是canvas?(了解) 是HTML5提供的一種新標(biāo)簽 Canvas是一個矩形區(qū)...
    J_L_L閱讀 1,522評論 0 4
  • 一摧扇、簡介 HTML5 中的定義:“它是依賴分辨率的位圖畫布圣贸,你可以在 canvas 上面繪制任何圖形,甚至加載照片...
    destiny0904閱讀 10,553評論 1 4