Canvas基礎(chǔ)


title: Canvas基礎(chǔ)
date: 2016-11-09
tags: HTML5


0x00 Canvas

使用 Canvas 元素必須為其設(shè)置寬度和高度屬性错负,指定可以繪制區(qū)域的大小致燥。如果不添加任何樣式或者不繪制任何圖形,那么是看不到該元素的论熙。

但是若是通過 CSS 樣式來為其設(shè)置寬高屬性的話,如果 CSS 的尺寸與 canvas 初始比例(canvas 默認初始寬度 300 px 高度 150 px)不一致,它會出現(xiàn)扭曲。

創(chuàng)建 Canvas 元素驾孔,并通過 canvas.getContext() 方法獲取其 2D 上下文。

// HTML 
<canvas id="myCanvas" width="400" height="400">A drawing of something.</canvas>

// JS
var drawing = $("#myCanvas")

if(drawing.getContext){
    // 確定瀏覽器是否支持 <canvas>
    var context = canvas.getContext("2d")
    // more code
}

如上惯疙,如果需要在畫布上繪圖翠勉,那么首先便需要獲得繪圖上下文。

然后霉颠,使用 canvas.toDataURL() 方法便可以獲取在 <canvas> 元素上繪制的圖像对碌,它只接受一個參數(shù),即是我們要指定圖像的 MIME 類型蒿偎。

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

0x01 2D 上下文

使用 2D 上下文可以繪制簡單的 2D 圖形朽们,比如矩形,弧線和路徑诉位。其兩種基本繪圖操作是填充(fillStyle)描邊(strokeStyle)


使用 strokeRect() 和 fillRect() 繪制矩形

可以使用 fillStyle() 屬性來為通過 fillRect() 繪制的矩形填充顏色骑脱;使用 strokeStyle() 屬性來為 strokeRect() 方繪制的矩形描邊

var drawing = $("#myCanvas")


if(drawing.getContext){
    // 檢測瀏覽器是支持 canvas
    
    var context1 = drawing.getContext("2d");    
    // 獲得 2d 上下文
    
    context1.fillStyle = "red"
    context1.fillRect(40,20,50,50)
    // 繪制一個矩形并填充 紅色

    context1.strokeStyle = "blue"   
    context1.strokeRect(10,10,50,50)
    // 繪制一個矩形并描邊為 藍色

}

此外,可以使用 clearRect() 方法來清除指定區(qū)域苍糠。


0x02 繪制路徑

一切形狀的原始基礎(chǔ)都是路徑叁丧。在 Cavans 創(chuàng)建一個形狀的首先需要的是創(chuàng)建新路徑(beginPath()),再通過繪圖命令(比如mouvTo()等)在路徑中繪制椿息,然后關(guān)閉路徑(clostPath())歹袁,最后填充顏色(fill())或描邊(stroke())。

調(diào)用fill()函數(shù)時寝优,所有沒有閉合的形狀都會自動閉合,所以你不需要調(diào)用closePath()函數(shù)枫耳。但是調(diào)用stroke()時不會自動閉合乏矾。

moveTo()

設(shè)置筆觸相對于畫布左上角開始的起點位置,即是路徑的起始點。

lineTo()

直線路徑钻心。

描邊三角形
var drawing = $("#myCanvas")
if(drawing.getContext){
    // 檢測瀏覽器是支持 canvas
    var context = drawing.getContext("2d"); 
    // 獲得 2d 上下文
    context.beginPath()
        context.strokeStyle = "green"
        context.moveTo(50,200)
        context.lineTo(200,100)
        context.lineTo(100,50)
        context.closePath()
        context.stroke()
    // 描邊三角形
}
描邊三角形
描邊填充三角形
var drawing = document.querySelector("#drawing")
if(drawing.getContext){
    //是否支持 canvas
context = drawing.getContext("2d")
// 獲得 2d 上下文
context.beginPath()
// 開始繪畫
context.fillStyle = "#333"
// 填充色為 #333
context.strokeStyle = "deeppink"
// 描邊顏色為 deeppink
context.lineWidth = "20"
// 線框為 20 px
context.moveTo(150,150)
// 起始觸點 (150,150)
context.lineTo(150,300)
context.lineTo(300,225)
// 繪制一個三角形
context.closePath()
// 閉合路勁
context.stroke()
// 描邊
context.fill()
// 填充
}
描邊填充三角形

arc() arcTo()

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

畫一個以(x,y)為圓心的以radius為半徑的圓黄嗯稹(圓),從startAngle開始到endAngle結(jié)束捷沸,按照anticlockwise給定的方向(默認為順時針)來生成摊沉。

arc() 函數(shù)中的角度單位是弧度,不是度數(shù)痒给。角度與弧度的js表達式:radians=(Math.PI/180)*degrees说墨。

描邊圓形
for(var i=0;i<6;i++){
    for(var j=0;j<6;j++){
        context.strokeStyle ='rgb(0,' + Math.floor(255-42.5*i) + ',' + Math.floor(255-42.5*j) + ')'
        context.beginPath()
        context.arc(50+60*i,50+60*j,30,0,Math.PI/180*360)
        context.stroke()
    }
}

源自 MDN 官網(wǎng)。

描邊填充圓形

描邊填充圓形苍柏,并使用 globalAlpha 設(shè)置其透明度為 0.3

context.beginPath()
context.strokeStyle = "deeppink"        
context.fillStyle ="#333"
context.globalAlpha = "0.3"
context.lineWidth = "20"
context.arc(450,300,100,0,Math.PI/180*300)
context.closePath()
context.stroke()
context.fill()
描邊填充圓形

0x03 漸變

Canvas 支持的漸變效果包括線性(createLinearGradient())和徑向(createRadialGradient())漸變,并使用addColorStop() 為其指定漸變顏色尼斧。

strokeStylefillStyle 屬性都可以接 canvasGradient 對象。

漸變顏色 addColorStop()

addColorStop(position,color) 中第一參數(shù) position 表示顏色出現(xiàn)在漸變中的相對位置试吁。

線性漸變 createLinearGradient()

createLinearGradient(x1,y1,x2,y2)棺棵,其所接收的四個參數(shù),分別代表漸變的起點和終點熄捍。

context.beginPath()
var lineGradient1 = context.createLinearGradient(100,200,100,400)
lineGradient1.addColorStop(0.5,"green")
lineGradient1.addColorStop(1,"red")
context.strokeStyle = lineGradient1
context.lineWidth = "20"
context.moveTo(100,200)
context.lineTo(100,400)
context.closePath()
context.stroke()
linearGradient
徑向漸變 createRadialGradient()

createRadialGradient(x1,y1,r1,x2,y2,r2) 方法接受 6 個參數(shù)烛恤,前三個定義一個以 (x1,y1) 為原點,半徑為 r1 的圓余耽,后三個參數(shù)則定義另一個以 (x2,y2) 為原點棒动,半徑為 r2 的圓。

// 創(chuàng)建漸變
var radGrad = context.createRadialGradient(0,150,40,0,140,90)
radGrad.addColorStop(0,'#00C9FF')
radGrad.addColorStop(0.8,'#00B5E2')
radGrad.addColorStop(1,'rgba(0,201,255,0)')

// 畫圖形
context.fillStyle = radGrad
context.fillRect(0,0,150,150)
radialGradient

0x04 繪制文本

文本樣式

  • font:這個字符串使用和 CSS 屬性相同的語法. 默認的字體是 10px sans-serif
  • textAlign:文本對齊方式宾添,可選值:start,end,left,right,center
  • textBaseline: 基線對齊方式船惨,可選值:top,middle,bottom
fillText(text,x,y,[,maxWidth])

在指定的(x,y)位置填充指定的文本,繪制的最大寬度(可選).

strokeText(text,x,y,[,maxWidth])

在指定的(x,y)位置繪制空心文本缕陕,繪制的最大寬度(可選).

var linGrad = context.createLinearGradient(50,50,400,200)
linGrad.addColorStop(0.2,"red")
linGrad.addColorStop(0.7,"deeppink")
// 設(shè)置漸變
var str = "to be or not to be "
context.beginPath()
context.font = "60px 宋體"
// 設(shè)置文字格式 必需
context.textAlign = "left"
// 設(shè)置文字對齊方式 必需
context.textBaseline = "middle"
// 設(shè)置文字基線 必需
context.shadowColor = "#333" 
context.shadowOffsetX = 10;
context.shadowOffsetY = 10;
context.shadowBlur = 10;
context.closePath()
// 閉合路徑
context.fillStyle = linGrad
// 設(shè)置 fillStyle
context.strokeStyle = linGrad
// 設(shè)置 strokeStyle 
context.fillText(str,50,50,400)
// 填充文字
context.strokeText(str,50,100,400)
// 描邊文字
console.log(context.measureText(str))//width:570

measureText() 方法粱锐,將返回一個 [TextMetrics
]對象的寬度、所在像素扛邑,這些體現(xiàn)文本特性的屬性怜浅。


0x05 Using Images

canvas 強大的特性還以使我們對圖像進行操作處理。

當然蔬崩,在對圖像進行操作之間必然要引入圖像資源恶座,canvas 支持多種不同的圖像資源引入方式,這里只了解常用的兩種方式:使用 Image 對象或 <img> 標簽 和 引用同一頁面中的另一畫布作為圖像資源.

drawImage(source,x,y)

圖像資源沥阳,以及在畫布中的起始位置

drawImage(source,x,y,width,height)

圖像資源跨琳,在畫布中的起始位置,并以指定的寬度和高度顯示在畫布中桐罕。以次實現(xiàn)圖像的縮放效果脉让。

var isImage = new Image;
isImage.src = "Koala.jpg"
isImage.onload = function(){
  // do drawingImage statement
  context.drawImage(isImage,60,60,400,400)
  //五個參數(shù)時桂敛,代表圖片在畫布中顯示的起始點和圖片顯示的寬高
}
五個參數(shù)
drawImage(source, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

當使用九個參數(shù)時,便是需要對圖像進行切片處理了溅潜。其中sx,sy,sWidth,sHeight 規(guī)定要在圖像源中取得的切片位置和切片大惺趸!;dx,dy,dWidht,dHeight 表示該切片在畫布中顯示的起始位置
和大小滚澜。

var isImage = new Image;
isImage.src = "Koala.jpg"
isImage.onload = function(){
    context.drawImage(isImage,300,300,400,300,100,100,200,200)
}
九個參數(shù)

createPattern()

我們可使用 createPattern() 方法來規(guī)定圖像顯示的方式粗仓,none,repeat,repeat-x,repeat-y

var isImage = new Image;
isImage.src = "Koala.jpg"
isImage.onload = function(){
    //圖片是否平鋪
    var imgs = context.createPattern(isImage,"repeat-x")
    context.fillStyle = imgs
    context.fillRect(0,0,700,500)
}

0x06 畫布裁切 clip()

var isImage = new Image;
isImage.src = "Koala.jpg"
isImage.onload = function(){
    context.drawImage(isImage,0,0,400,400)
}
//畫布裁切 clip()
context.arc(230,230,170,0,Math.PI/180*360)
context.closePath()
context.clip()
畫布裁切

0x07 畫布方法

save() 和 restore()

save 和 restore 方法是用來保存和恢復(fù) canvas 狀態(tài)的,都沒有參數(shù)设捐。Canvas 的狀態(tài)就是當前畫面應(yīng)用的所有樣式和變形的一個快照借浊。

context.beginPath()
context.fillRect(50,50,150,150)
// 使用默認設(shè)置繪制一個矩形
context.save()
// 保存默認配置下的繪畫狀態(tài)
context.fillStyle = "deeppink"
// 設(shè)置一個新的繪畫狀態(tài)
context.fillRect(65,65,120,120)
// 使用新的繪制狀態(tài)繪制一個矩形
context.restore()
// 恢復(fù)到默認繪制狀態(tài)
context.fillRect(80,80,90,90)
// 同樣,使用默認狀態(tài)繪制一個矩形

restore() 恢復(fù)的是離它最近的 save() 之上 所保存的狀態(tài)挡育。

translate()

transltae(x,y) 方法用 移動 canvas 原點巴碗。

context.fillRect(50,50,100,100)
context.translate(100,100)
context.fillRect(50,50,100,100)
translate
scale(x,y)

scale(x,y) 縮放即寒,其所接收的兩個參數(shù)分別代表在 x 的縮放因子和在 y 軸的縮放因子橡淆。

context.scale(1.5,1.5)
context.fillRect(50,50,100,100)
context.translate(150,150)
context.scale(0.5,0.5)
context.fillRect(50,50,100,100)
rotate()

rotate(angle) 只接受一個參數(shù),即旋轉(zhuǎn)的角度母赵,它是順時針方向的逸爵,與 arc() 同樣是以 弧度 為單位的值。

context.rotate(Math.PI/180*deg)

scale 也好凹嘲,translate,rotate() 也好师倔,所有的樣式和變形命令都應(yīng)該寫在填充和描邊命令之前。


0x08 畫一個五角星

var r = 200
context.translate(200,200)
context.beginPath()
context.moveTo(r,0)
for(var i=0;i<9;i++){
    context.rotate(Math.PI/180*36)
    if(i%2 == 0){
        context.lineTo(r/(Math.cos(Math.PI/180*36)*2)*0.7,0)
    }else{
        context.lineTo(r,0)
    }
}
context.closePath()
context.fill()
}
五角星
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末周蹭,一起剝皮案震驚了整個濱河市趋艘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凶朗,老刑警劉巖瓷胧,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異棚愤,居然都是意外死亡搓萧,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門宛畦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瘸洛,“玉大人,你說我怎么就攤上這事次和》蠢撸” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵斯够,是天一觀的道長囚玫。 經(jīng)常有香客問我喧锦,道長读规,這世上最難降的妖魔是什么抓督? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮束亏,結(jié)果婚禮上铃在,老公的妹妹穿的比我還像新娘。我一直安慰自己碍遍,他們只是感情好定铜,可當我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著怕敬,像睡著了一般揣炕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上东跪,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天畸陡,我揣著相機與錄音,去河邊找鬼虽填。 笑死丁恭,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的斋日。 我是一名探鬼主播牲览,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼恶守!你這毒婦竟也來了第献?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤兔港,失蹤者是張志新(化名)和其女友劉穎庸毫,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體押框,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡岔绸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了橡伞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盒揉。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖兑徘,靈堂內(nèi)的尸體忽然破棺而出刚盈,到底是詐尸還是另有隱情,我是刑警寧澤挂脑,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布藕漱,位于F島的核電站欲侮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏肋联。R本人自食惡果不足惜威蕉,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望橄仍。 院中可真熱鬧韧涨,春花似錦、人聲如沸侮繁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宪哩。三九已至娩贷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锁孟,已是汗流浹背彬祖。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留罗岖,地道東北人涧至。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像桑包,于是被迫代替她去往敵國和親南蓬。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,914評論 2 355

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