JavaScript第十五章節(jié) 使用Canvas繪圖(2D)

基本用法

要使用<canvas>元素则剃,必須先設(shè)置其 width 和 height 屬性甘有,指定可以繪圖的區(qū)域大小腔长。出現(xiàn)在
開始和結(jié)束標(biāo)簽中的內(nèi)容是后備信息,如果瀏覽器不支持<canvas>元素遏插,就會(huì)顯示這些信息捂贿。

示例:

<canvas id="drawing" width=" 200" height="200">A drawing of something.</canvas> 

要在這塊畫布(canvas)上繪圖,需要取得繪圖上下文胳嘲。而取得繪圖上下文對(duì)象的引用厂僧,需要調(diào)用
getContext()方法并傳入上下文的名字。傳入"2d"了牛,就可以取得 2D 上下文對(duì)象颜屠。

示例:

var drawing = document.getElementById("drawing");
//確定瀏覽器支持<canvas>元素
if (drawing.getContext){ 
    //獲取2D上下文對(duì)象
    var context = drawing.getContext("2d");
    //更多代碼
} 

使用 toDataURL()方法,可以導(dǎo)出在<canvas>元素上繪制的圖像白魂。這個(gè)方法接受一個(gè)參數(shù)汽纤,即圖
像的 MIME 類型格式,而且適合用于創(chuàng)建圖像的任何上下文福荸。比如蕴坪,要取得畫布中的一幅 PNG 格式的
圖像,可以使用以下代碼。

var drawing = document.getElementById("drawing");
//確定瀏覽器支持<canvas>元素
if (drawing.getContext){
 //取得圖像的數(shù)據(jù) URI
 var imgURI = drawing.toDataURL("image/png");
 //顯示圖像
 var image = document.createElement("img");
 image.src = imgURI;
 document.body.appendChild(image);
} 

默認(rèn)情況下背传,瀏覽器會(huì)將圖像編碼為 PNG 格式(除非另行指定)呆瞻。Firefox 和 Opera 也支持基于
"image/jpeg"參數(shù)的 JPEG 編碼格式。由于這個(gè)方法是后來才追加的径玖,所以支持<canvas>的瀏覽器也
是在較新的版本中才加入了對(duì)它的支持痴脾,比如 IE9、Firefox 3.5 和 Opera 10梳星。

注意:如果繪制到畫布上的圖像源自不同的域赞赖,toDataURL()方法會(huì)拋出錯(cuò)誤。

2D上下文

使用 2D 繪圖上下文提供的方法冤灾,可以繪制簡單的 2D 圖形前域,比如矩形、弧線和路徑韵吨。2D 上下文的
坐標(biāo)開始于<canvas>元素的左上角匿垄,原點(diǎn)坐標(biāo)是(0,0)。所有坐標(biāo)值都基于這個(gè)原點(diǎn)計(jì)算归粉,x 值越大表示
越靠右椿疗,y 值越大表示越靠下。默認(rèn)情況下糠悼,width 和 height 表示水平和垂直兩個(gè)方向上可用的像素
數(shù)目届榄。

填充和描邊

2D 上下文的兩種基本繪圖操作是填充和描邊。填充绢掰,就是用指定的樣式(顏色痒蓬、漸變或圖像)填
充圖形;描邊滴劲,就是只在圖形的邊緣畫線攻晒。大多數(shù) 2D 上下文操作都會(huì)細(xì)分為填充和描邊兩個(gè)操作,而操作的結(jié)果取決于兩個(gè)屬性:fillStyle 和 strokeStyle班挖。
這兩個(gè)屬性的值可以是字符串鲁捏、漸變對(duì)象或模式對(duì)象,而且它們的默認(rèn)值都是"#000000"萧芙。如果為
它們指定表示顏色的字符串值给梅,可以使用 CSS 中指定顏色值的任何格式,包括顏色名双揪、十六進(jìn)制碼动羽、
rgb、rgba渔期、hsl 或 hsla运吓。

示例:

var drawing = document.getElementById("drawing");
//確定瀏覽器支持<canvas>元素
if (drawing.getContext){
 var context = drawing.getContext("2d");
 context.strokeStyle = "red";
 context.fillStyle = "#0000ff";
} 

繪制矩形

矩形是唯一一種可以直接在 2D 上下文中繪制的形狀渴邦。與矩形有關(guān)的方法包括 fillRect()、
strokeRect()和 clearRect()拘哨。這三個(gè)方法都能接收 4 個(gè)參數(shù):矩形的 x 坐標(biāo)谋梭、矩形的 y 坐標(biāo)、矩形
寬度和矩形高度倦青。這些參數(shù)的單位都是像素瓮床。

示例:

var drawing = document.getElementById("drawing");
//確定瀏覽器支持<canvas>元素
if (drawing.getContext){
 var context = drawing.getContext("2d");
 /*
 * 根據(jù) Mozilla 的文檔
 * http://developer.mozilla.org/en/docs/Canvas_tutorial:Basic_usage
 */
 //繪制紅色矩形
 context.fillStyle = "#ff0000";
 context.fillRect(10, 10, 50, 50);
 //繪制半透明的藍(lán)色矩形
 context.fillStyle = "rgba(0,0,255,0.5)";
 context.fillRect(30, 30, 50, 50);
} 

strokeRect()方法在畫布上繪制的矩形會(huì)使用指定的顏色描邊。描邊顏色通
過 strokeStyle 屬性指定产镐。

示例:

var drawing = document.getElementById("drawing");
//確定瀏覽器支持<canvas>元素
if (drawing.getContext){
 var context = drawing.getContext("2d");
 /*
 * 根據(jù) Mozilla 的文檔
 * http://developer.mozilla.org/en/docs/Canvas_tutorial:Basic_usage
 */
 //繪制紅色描邊矩形
 context.strokeStyle = "#ff0000";
 context.strokeRect(10, 10, 50, 50);
 //繪制半透明的藍(lán)色描邊矩形
 context.strokeStyle = "rgba(0,0,255,0.5)";
 context.strokeRect(30, 30, 50, 50);
} 

描邊線條的寬度由 lineWidth 屬性控制隘庄,該屬性的值可以是任意整數(shù)。另外磷账,
通過 lineCap 屬性可以控制線條末端的形狀是平頭峭沦、圓頭還是方頭("butt"、
"round"或"square")逃糟,通過 lineJoin 屬性可以控制線條相交的方式是圓交、斜
交還是斜接("round"蓬豁、"bevel"或"miter")绰咽。

clearRect()方法用于清除畫布上的矩形區(qū)域。本質(zhì)上地粪,這個(gè)方法可以把繪制上下文中的某
一矩形區(qū)域變透明取募。通過繪制形狀然后再清除指定區(qū)域,就可以生成有意思的效果蟆技,例如把某個(gè)形狀切
掉一塊玩敏。

示例:

var drawing = document.getElementById("drawing");
//確定瀏覽器支持<canvas>元素
if (drawing.getContext){
 var context = drawing.getContext("2d");
 /*
 * 根據(jù) Mozilla 的文檔
 * http://developer.mozilla.org/en/docs/Canvas_tutorial:Basic_usage
 */
 //繪制紅色矩形
 context.fillStyle = "#ff0000";
 context.fillRect(10, 10, 50, 50);
 //繪制半透明的藍(lán)色矩形
 context.fillStyle = "rgba(0,0,255,0.5)";
 context.fillRect(30, 30, 50, 50);
 //在兩個(gè)矩形重疊的地方清除一個(gè)小矩形
 context.clearRect(40, 40, 10, 10);
} 

繪制路徑

2D 繪制上下文支持很多在畫布上繪制路徑的方法。通過路徑可以創(chuàng)造出復(fù)
雜的形狀和線條质礼。要繪制路徑旺聚,首先必須調(diào)用 beginPath()方法,表示要開始
繪制新路徑眶蕉。然后砰粹,再通過調(diào)用下列方法來實(shí)際地繪制路徑。

  • arc(x, y, radius, startAngle, endAngle, counterclockwise):以(x,y)為圓心繪
    制一條弧線造挽,弧線半徑為 radius碱璃,起始和結(jié)束角度(用弧度表示)分別為 startAngle 和
    endAngle。最后一個(gè)參數(shù)表示 startAngle 和 endAngle 是否按逆時(shí)針方向計(jì)算饭入,值為 false
    表示按順時(shí)針方向計(jì)算嵌器。
  • arcTo(x1, y1, x2, y2, radius):從上一點(diǎn)開始繪制一條弧線,到(x2,y2)為止谐丢,并且以
    給定的半徑 radius 穿過(x1,y1)爽航。
  • bezierCurveTo(c1x, c1y, c2x, c2y, x, y):從上一點(diǎn)開始繪制一條曲線,到(x,y)為
    止,并且以(c1x,c1y)和(c2x,c2y)為控制點(diǎn)岳掐。
  • lineTo(x, y):從上一點(diǎn)開始繪制一條直線凭疮,到(x,y)為止。
  • moveTo(x, y):將繪圖游標(biāo)移動(dòng)到(x,y)串述,不畫線执解。
  • quadraticCurveTo(cx, cy, x, y):從上一點(diǎn)開始繪制一條二次曲線,到(x,y)為止纲酗,并
    且以(cx,cy)作為控制點(diǎn)衰腌。
  • rect(x, y, width, height):從點(diǎn)(x,y)開始繪制一個(gè)矩形,寬度和高度分別由 width 和
    height 指定觅赊。這個(gè)方法繪制的是矩形路徑右蕊,而不是 strokeRect()和 fillRect()所繪制的獨(dú)
    立的形狀。
  • closePath():把起點(diǎn)連接起來
  • fill():在路徑已經(jīng)完成的情況下吮螺,填充
  • stroke():對(duì)路徑進(jìn)行描邊

示例:

var drawing = document.getElementById("drawing");
//確定瀏覽器支持<canvas>元素
if (drawing.getContext){
 var context = drawing.getContext("2d");
 //開始路徑
 context.beginPath();
 //繪制外圓
 context.arc(100, 100, 99, 0, 2 * Math.PI, false);
 //繪制內(nèi)圓
 context.moveTo(194, 100);
 context.arc(100, 100, 94, 0, 2 * Math.PI, false);
 //繪制分針
 context.moveTo(100, 100);
 context.lineTo(100, 15);
 //繪制時(shí)針
 context.moveTo(100, 100);
 context.lineTo(35, 100);
 //描邊路徑
 context.stroke();
} 

繪制文本

文本與圖形總是如影隨形饶囚。為此,2D 繪圖上下文也提供了繪制文本的方法鸠补。繪制文本主要有兩個(gè)
方法:fillText()和 strokeText()萝风。這兩個(gè)方法都可以接收 4 個(gè)參數(shù):要繪制的文本字符串、x 坐
標(biāo)紫岩、y 坐標(biāo)和可選的最大像素寬度规惰。而且,這兩個(gè)方法都以下列 3 個(gè)屬性為基礎(chǔ)

  • font:表示文本樣式泉蝌、大小及字體歇万,用 CSS 中指定字體的格式來指定,例如"10px Arial"勋陪。
  • textAlign:表示文本對(duì)齊方式贪磺。可能的值有"start"粥鞋、"end"缘挽、"left"、"right"和"center"呻粹。
    建議使用"start"和"end"壕曼,不要使用"left"和"right",因?yàn)榍皟烧叩囊馑几€(wěn)妥等浊,能同時(shí)
    適合從左到右和從右到左顯示(閱讀)的語言腮郊。
  • textBaseline:表示文本的基線〕镅啵可能的值有"top"轧飞、"hanging"衅鹿、"middle"、"alphabetic"过咬、
    "ideographic"和"bottom"大渤。
  • measureText():這個(gè)方法接收一個(gè)參數(shù),即要繪制的文本掸绞;返回一個(gè) TextMetrics
    對(duì)象泵三。返回的對(duì)象目前只有一個(gè) width 屬性

變換

通過上下文的變換,可以把處理后的圖像繪制到畫布上衔掸。2D 繪制上下文支持各種基本的繪制變換烫幕。
創(chuàng)建繪制上下文時(shí),會(huì)以默認(rèn)值初始化變換矩陣敞映,在默認(rèn)的變換矩陣下较曼,所有處理都按描述直接繪制。
為繪制上下文應(yīng)用變換振愿,會(huì)導(dǎo)致使用不同的變換矩陣應(yīng)用處理捷犹,從而產(chǎn)生不同的結(jié)果。

  • rotate(angle):圍繞原點(diǎn)旋轉(zhuǎn)圖像 angle 弧度冕末。
  • scale(scaleX, scaleY):縮放圖像伏恐,在 x 方向乘以 scaleX,在 y 方向乘以 scaleY栓霜。scaleX
    和 scaleY 的默認(rèn)值都是 1.0。
  • translate(x, y):將坐標(biāo)原點(diǎn)移動(dòng)到(x,y)横蜒。執(zhí)行這個(gè)變換之后胳蛮,坐標(biāo)(0,0)會(huì)變成之前由(x,y)
    表示的點(diǎn)。
  • transform(m1_1, m1_2, m2_1, m2_2, dx, dy):直接修改變換矩陣丛晌,方式是乘以如下
    矩陣仅炊。
    m1_1 m1_2 dx
    m2_1 m2_2 dy
    0 0 1
  • setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy):將變換矩陣重置為默認(rèn)狀態(tài),然后
    再調(diào)用 transform()澎蛛。

繪制圖像

2D 繪圖上下文內(nèi)置了對(duì)圖像的支持抚垄。如果你想把一幅圖像繪制到畫布上,可以使用 drawImage()
方法谋逻。根據(jù)期望的最終結(jié)果不同呆馁,調(diào)用這個(gè)方法時(shí),可以使用三種不同的參數(shù)組合毁兆。最簡單的調(diào)用方式
是傳入一個(gè) HTML <img>元素浙滤,以及繪制該圖像的起點(diǎn)的 x 和 y 坐標(biāo)。

  • drawImage():總共需要傳入 9 個(gè)參數(shù):要繪制的圖像气堕、源圖像的 x 坐標(biāo)纺腊、源圖像的 y 坐標(biāo)畔咧、源圖像的寬度、源
    圖像的高度揖膜、目標(biāo)圖像的 x 坐標(biāo)誓沸、目標(biāo)圖像的 y 坐標(biāo)、目標(biāo)圖像的寬度壹粟、目標(biāo)圖像的高度拜隧。

陰影

2D 上下文會(huì)根據(jù)以下幾個(gè)屬性的值,自動(dòng)為形狀或路徑繪制出陰影煮寡。

  • shadowColor:用 CSS 顏色格式表示的陰影顏色虹蓄,默認(rèn)為黑色。
  • shadowOffsetX:形狀或路徑 x 軸方向的陰影偏移量幸撕,默認(rèn)為 0薇组。
  • shadowOffsetY:形狀或路徑 y 軸方向的陰影偏移量,默認(rèn)為 0坐儿。
  • shadowBlur:模糊的像素?cái)?shù)律胀,默認(rèn) 0,即不模糊貌矿。

漸變

漸變由 CanvasGradient 實(shí)例表示炭菌,很容易通過 2D 上下文來創(chuàng)建和修改。要?jiǎng)?chuàng)建一個(gè)新的線性漸
變逛漫,可以調(diào)用 createLinearGradient()方法黑低。這個(gè)方法接收 4 個(gè)參數(shù):起點(diǎn)的 x 坐標(biāo)、起點(diǎn)的 y 坐
標(biāo)酌毡、終點(diǎn)的 x 坐標(biāo)克握、終點(diǎn)的 y 坐標(biāo)。

  • createLinearGradient():線性漸變枷踏,這個(gè)方法接收 4 個(gè)參數(shù):起點(diǎn)的 x 坐標(biāo)菩暗、起點(diǎn)的 y 坐
    標(biāo)、終點(diǎn)的 x 坐標(biāo)旭蠕、終點(diǎn)的 y 坐標(biāo)停团。
  • createRadialGradient():徑向漸變,這個(gè)方法接收 6 個(gè)參
    數(shù)掏熬,對(duì)應(yīng)著兩個(gè)圓的圓心和半徑佑稠。前三個(gè)參數(shù)指定的是起點(diǎn)圓的原心(x 和 y)及半徑,后三個(gè)參數(shù)指
    定的是終點(diǎn)圓的原心(x 和 y)及半徑孽江。

模式

模式其實(shí)就是重復(fù)的圖像讶坯,可以用來填充或描邊圖形。

  • createPattern():傳入兩個(gè)參數(shù):一個(gè) HTML <img>元素和一個(gè)表示如何重復(fù)圖像的字符串岗屏。
    其中辆琅,第二個(gè)參數(shù)的值與 CSS 的 background-repeat 屬性值相同

使用圖像數(shù)據(jù)

2D 上下文的一個(gè)明顯的長處就是漱办,可以通過 getImageData()取得原始圖像數(shù)據(jù)。這個(gè)方法接收
4 個(gè)參數(shù):要取得其數(shù)據(jù)的畫面區(qū)域的 x 和 y 坐標(biāo)以及該區(qū)域的像素寬度和高度婉烟。

  • getImageData():接收
    4 個(gè)參數(shù):要取得其數(shù)據(jù)的畫面區(qū)域的 x 和 y 坐標(biāo)以及該區(qū)域的像素寬度和高度娩井。

返回的對(duì)象是 ImageData 的實(shí)例。每個(gè) ImageData 對(duì)象都有三個(gè)屬性:width似袁、height 和
data洞辣。其中 data 屬性是一個(gè)數(shù)組,保存著圖像中每一個(gè)像素的數(shù)據(jù)昙衅。

合成

還有兩個(gè)會(huì)應(yīng)用到 2D 上下文中所有繪制操作的屬性:globalAlpha 和 globalCompositionOperation扬霜。

  • globalAlpha:0 - 1之間的值
  • globalCompositionOperation:
    • source-over(默認(rèn)值):后繪制的圖形位于先繪制的圖形上方。
    • source-in:后繪制的圖形與先繪制的圖形重疊的部分可見而涉,兩者其他部分完全透明著瓶。
    • source-out:后繪制的圖形與先繪制的圖形不重疊的部分可見,先繪制的圖形完全透明啼县。
    • source-atop:后繪制的圖形與先繪制的圖形重疊的部分可見材原,先繪制圖形不受影響。
    • destination-over:后繪制的圖形位于先繪制的圖形下方季眷,只有之前透明像素下的部分才可見余蟹。
    • destination-in:后繪制的圖形位于先繪制的圖形下方,兩者不重疊的部分完全透明子刮。
    • destination-out:后繪制的圖形擦除與先繪制的圖形重疊的部分威酒。
    • destination-atop:后繪制的圖形位于先繪制的圖形下方,在兩者不重疊的地方挺峡,先繪制的圖形會(huì)變透明兼搏。
    • lighter:后繪制的圖形與先繪制的圖形重疊部分的值相加,使該部分變亮沙郭。
    • copy:后繪制的圖形完全替代與之重疊的先繪制圖形。
    • xor:后繪制的圖形與先繪制的圖形重疊的部分執(zhí)行“異或”操作裳朋。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末病线,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子鲤嫡,更是在濱河造成了極大的恐慌送挑,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件暖眼,死亡現(xiàn)場(chǎng)離奇詭異惕耕,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)诫肠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門司澎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來欺缘,“玉大人,你說我怎么就攤上這事挤安⊙枋猓” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵蛤铜,是天一觀的道長嫩絮。 經(jīng)常有香客問我,道長围肥,這世上最難降的妖魔是什么剿干? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮穆刻,結(jié)果婚禮上置尔,老公的妹妹穿的比我還像新娘。我一直安慰自己蛹批,他們只是感情好撰洗,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著腐芍,像睡著了一般差导。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上猪勇,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天设褐,我揣著相機(jī)與錄音,去河邊找鬼泣刹。 笑死助析,一個(gè)胖子當(dāng)著我的面吹牛畦粮,可吹牛的內(nèi)容都是我干的嘁傀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼媳溺,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼掀泳!你這毒婦竟也來了雪隧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤员舵,失蹤者是張志新(化名)和其女友劉穎脑沿,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體马僻,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡庄拇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了韭邓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片措近。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡溶弟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出熄诡,到底是詐尸還是另有隱情可很,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布凰浮,位于F島的核電站我抠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏袜茧。R本人自食惡果不足惜菜拓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望笛厦。 院中可真熱鬧纳鼎,春花似錦、人聲如沸裳凸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姨谷。三九已至逗宁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間梦湘,已是汗流浹背瞎颗。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捌议,地道東北人哼拔。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像瓣颅,于是被迫代替她去往敵國和親倦逐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

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