摘要:二次以及三次貝塞爾曲線都十分有用,一般用來(lái)繪制復(fù)雜有規(guī)律的圖形。繪制三次貝塞爾曲線,為結(jié)束點(diǎn),為控制點(diǎn)一,為控制點(diǎn)二。下邊的圖能夠很好的描述兩者的關(guān)系,二次貝塞爾曲線有一個(gè)開始結(jié)束點(diǎn)藍(lán)色以及一個(gè)控制點(diǎn)紅色,而三次貝塞爾曲線使用兩個(gè)控制點(diǎn)。
Canvas tutorial 您的瀏覽器不支持canvas
模板看起來(lái)會(huì)是這樣。如這里所示,它最初是空白的。
一個(gè)簡(jiǎn)單例子
一開始,讓我們來(lái)看個(gè)簡(jiǎn)單的例子,我們繪制了兩個(gè)有趣的長(zhǎng)方形,其中的一個(gè)有著alpha透明度。我們將在接下來(lái)的例子里深入探索一下這是如何工作的。
效果
在我們開始畫圖之前,我們需要了解一下畫布柵格(canvas grid)以及坐標(biāo)空間。上一頁(yè)中的HTML模板中有個(gè)寬150px, 高150px的canvas元素。如右圖所示,canvas元素默認(rèn)被網(wǎng)格所覆蓋。通常來(lái)說(shuō)網(wǎng)格中的一個(gè)單元相當(dāng)于canvas元素中的一像素。柵格的起點(diǎn)為左上角(坐標(biāo)為(0,0))。所有元素的位置都相對(duì)于原點(diǎn)定位。所以圖中藍(lán)色方形左上角的坐標(biāo)為距離左邊(Y軸)x像素,距離上邊(X軸)y像素(坐標(biāo)為(x,y))。在課程的最后我們會(huì)平移原點(diǎn)到不同的坐標(biāo)上,旋轉(zhuǎn)網(wǎng)格以及縮放。現(xiàn)在我們還是使用原來(lái)的設(shè)置。
HTML中的元素canvas只支持一種原生的圖形繪制:矩形。所有其他的圖形的繪制都至少需要生成一條路徑。不過(guò),我們擁有眾多路徑生成的方法讓復(fù)雜圖形的繪制成為了可能。
首先,我們回到矩形的繪制中。canvas提供了三種方法繪制矩形:
fillRect(x, y, width, height)
繪制一個(gè)填充的矩形
strokeRect(x, y, width, height)
繪制一個(gè)矩形的邊框
clearRect(x, y, width, height)
清除指定矩形區(qū)域,讓清除部分完全透明,例如一個(gè)鏤空的矩形。
上面提供的方法之中每一個(gè)都包含了相同的參數(shù)。x與y指定了在canvas畫布上所繪制的矩形的左上角(相對(duì)于原點(diǎn))的坐標(biāo)。width和height設(shè)置矩形的尺寸。
下面的draw() 函數(shù)是前面中取得的,現(xiàn)在就來(lái)使用上面的三個(gè)函數(shù)。
function draw() { var canvas = document.getElementById("canvas"); if (canvas.getContext) { var ctx = canvas.getContext("2d"); ctx.fillRect(25,25,100,100); ctx.clearRect(45,45,60,60); ctx.strokeRect(50,50,50,50); } }
效果
fillRect()函數(shù)繪制了一個(gè)邊長(zhǎng)為100px的黑色正方形。clearRect()函數(shù)從正方形的中心開始擦除了一個(gè)6060px的正方形,接著strokeRect()在清除區(qū)域內(nèi)生成一個(gè)5050的正方形邊框。
繪制路徑
圖形的基本元素是路徑。路徑是通過(guò)不同顏色和寬度的線段或曲線相連形成的不同形狀的點(diǎn)的集合。一個(gè)路徑,甚至一個(gè)子路徑,都是閉合的。使用路徑繪制圖形需要一些額外的步驟。
首先,你需要?jiǎng)?chuàng)建路徑起始點(diǎn)。
然后你使用畫圖命令去畫出路徑。
之后你把路徑封閉。
一旦路徑生成,你就能通過(guò)描邊或填充路徑區(qū)域來(lái)渲染圖形。
以下是所要用到的函數(shù):
beginPath()
新建一條路徑,生成之后,圖形繪制命令被指向到路徑上生成路徑。
closePath()
閉合路徑之后圖形繪制命令又重新指向到上下文中。
stroke()
通過(guò)線條來(lái)繪制圖形輪廓。
fill()
通過(guò)填充路徑的內(nèi)容區(qū)域生成實(shí)心的圖形。
生成路徑:
第一步叫做beginPath()。本質(zhì)上,路徑是由很多子路徑構(gòu)成,這些子路徑都是在一個(gè)列表中,所有的子路徑(線、弧形、等等)構(gòu)成圖形。而每次這個(gè)方法調(diào)用之后,列表清空重置,然后我們就可以重新繪制新的圖形。
第二步就是調(diào)用函數(shù)指定繪制路徑,本文稍后我們就能看到了。
第三,就是閉合路徑closePath(),不是必需的。這個(gè)方法會(huì)通過(guò)繪制一條從當(dāng)前點(diǎn)到開始點(diǎn)的直線來(lái)閉合圖形。如果圖形是已經(jīng)閉合了的,即當(dāng)前點(diǎn)為開始點(diǎn),該函數(shù)什么也不做。
繪制一個(gè)三角形
function draw() { var canvas = document.getElementById("canvas"); if (canvas.getContext){ var ctx = canvas.getContext("2d"); ctx.beginPath(); ctx.moveTo(75,50); ctx.lineTo(100,75); ctx.lineTo(100,25); ctx.fill(); } }
效果
移動(dòng)筆觸
一個(gè)非常有用的函數(shù),而這個(gè)函數(shù)實(shí)際上并不能畫出任何東西,也是上面所描述的路徑列表的一部分,這個(gè)函數(shù)就是moveTo()。或者你可以想象一下在紙上作業(yè),一支鋼筆或者鉛筆的筆尖從一個(gè)點(diǎn)到另一個(gè)點(diǎn)的移動(dòng)過(guò)程。
moveTo(x, y)
將筆觸移動(dòng)到指定的坐標(biāo)x以及y上。
當(dāng)canvas初始化或者beginPath()調(diào)用后,你通常會(huì)使用moveTo()函數(shù)設(shè)置起點(diǎn)。我們也能夠使用moveTo()繪制一些不連續(xù)的路徑。看一下下面的笑臉例子。我將用到moveTo()方法(紅線處)的地方標(biāo)記了。
你可以嘗試一下,使用下邊的代碼片。只需要將其復(fù)制到之前的draw()函數(shù)即可。
function draw() { var canvas = document.getElementById("canvas"); if (canvas.getContext){ var ctx = canvas.getContext("2d"); ctx.beginPath(); ctx.arc(75,75,50,0,Math.PI*2,true); // 繪制 ctx.moveTo(110,75); ctx.arc(75,75,35,0,Math.PI,false); // 口(順時(shí)針) ctx.moveTo(65,65); ctx.arc(60,65,5,0,Math.PI*2,true); // 左眼 ctx.moveTo(95,65); ctx.arc(90,65,5,0,Math.PI*2,true); // 右眼 ctx.stroke(); } }
效果
arc()函數(shù)介紹:
由于canvas中所有于角有關(guān)的API,都需要以弧度(R)來(lái)指定該角的值。三角函數(shù)也都采用弧度制。所以需要記好以下公式:
180度=π弧度
1弧度=(π/180)×度
1度=(180/π)×弧度
π=3.14,所以45度等于(3.14/180)×45度得0.7853弧度
如果你想看到連續(xù)的線,你可以移除調(diào)用的moveTo()。
線
繪制直線,需要用到的方法lineTo()。
lineTo(x, y)
繪制一條從當(dāng)前位置到指定x以及y位置的直線。
該方法有兩個(gè)參數(shù):x以及y ,代表坐標(biāo)系中直線結(jié)束的點(diǎn)。開始點(diǎn)和之前的繪制路徑有關(guān),之前路徑的結(jié)束點(diǎn)就是接下來(lái)的開始點(diǎn),等等。。。開始點(diǎn)也可以通過(guò)moveTo()函數(shù)改變。
下面的例子繪制兩個(gè)三角形,一個(gè)是填充的,另一個(gè)是描邊的。
function draw() { var canvas = document.getElementById("canvas"); if (canvas.getContext){ var ctx = canvas.getContext("2d"); // 填充三角形 ctx.beginPath(); ctx.moveTo(25,25); ctx.lineTo(105,25); ctx.lineTo(25,105); ctx.fill(); // 描邊三角形 ctx.beginPath(); ctx.moveTo(125,125); ctx.lineTo(125,45); ctx.lineTo(45,125); ctx.closePath(); ctx.stroke(); } }
這里從調(diào)用beginPath()函數(shù)準(zhǔn)備繪制一個(gè)新的形狀路徑開始。然后使用moveTo()函數(shù)移動(dòng)到目標(biāo)位置上。然后下面,兩條線段繪制后構(gòu)成三角形的兩條邊。
你會(huì)注意到填充與描邊三角形步驟有所不同。正如上面所提到的,因?yàn)槁窂绞褂锰畛洌╢illed)時(shí),路徑自動(dòng)閉合,使用描邊(stroked)則不會(huì)閉合路徑。如果沒(méi)有添加閉合路徑closePath()到描述三角形函數(shù)中,則只繪制了兩條線段,并不是一個(gè)完整的三角形。
圓弧
繪制圓弧或者圓,我們使用arc()方法。當(dāng)然可以使用arcTo(),不過(guò)這個(gè)的現(xiàn)實(shí)并不是那么的可靠,所以我們這里不作介紹。
arc(x, y, radius, startAngle, endAngle, anticlockwise)
畫一個(gè)以(x,y)為圓心的以radius為半徑的圓弧(圓),從startAngle開始到endAngle結(jié)束,按照anticlockwise給定的方向(默認(rèn)為順時(shí)針)來(lái)生成。
arcTo(x1, y1, x2, y2, radius)
根據(jù)給定的控制點(diǎn)和半徑畫一段圓弧,再以直線連接兩個(gè)控制點(diǎn)。
該方法有五個(gè)參數(shù):x,y為繪制圓弧所在圓上的圓心坐標(biāo)。radius為半徑。startAngle以及endAngle參數(shù)用弧度定義了開始以及結(jié)束的弧度。這些都是以x軸為基準(zhǔn)。參數(shù)anticlockwise 為一個(gè)布爾值。為true時(shí),是逆時(shí)針?lè)较颍駝t順時(shí)針?lè)较颉?br>下面的例子比上面的要復(fù)雜一下,下面繪制了12個(gè)不同的角度以及填充的圓弧。
下面兩個(gè)for循環(huán),生成圓弧的行列(x,y)坐標(biāo)。每一段圓弧的開始都調(diào)用beginPath()。代碼中,每個(gè)圓弧的參數(shù)都是可變的,實(shí)際生活中,我們并不需要這樣做。
x,y坐標(biāo)是可變的。半徑(radius)和開始角度(startAngle)都是固定的。結(jié)束角度(endAngle)在第一列開始時(shí)是180度(半圓)然后每列增加90度。最后一列形成一個(gè)完整的圓。
clockwise 語(yǔ)句作用于第一、三行是順時(shí)針的圓弧,anticlockwise作用于二、四行為逆時(shí)針圓弧。if 語(yǔ)句讓一、二行描邊圓弧,下面兩行填充路徑。
function draw() { var canvas = document.getElementById("canvas"); if (canvas.getContext){ var ctx = canvas.getContext("2d"); for(var i=0;i<4;i++){ for(var j=0;j<3;j++){ ctx.beginPath(); var x = 25+j*50; // x 坐標(biāo)值 var y = 25+i*50; // y 坐標(biāo)值 var radius = 20; // 圓弧半徑 var startAngle = 0; // 開始點(diǎn) var endAngle = Math.PI+(Math.PI*j)/2; // 結(jié)束點(diǎn) var anticlockwise = i%2==0 ? false : true; // 順時(shí)針或逆時(shí)針 ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise); if (i>1){ ctx.fill(); } else { ctx.stroke(); } } } } }
效果
貝塞爾(bezier)以及二次貝塞爾
下一個(gè)十分有用的路徑類型就是 貝塞爾曲線。二次以及三次貝塞爾曲線都十分有用,一般用來(lái)繪制復(fù)雜有規(guī)律的圖形。
quadraticCurveTo(cp1x, cp1y, x, y)
繪制二次貝塞爾曲線,x,y為結(jié)束點(diǎn),cp1x,cp1y為控制點(diǎn)。
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
繪制三次貝塞爾曲線,x,y為結(jié)束點(diǎn),cp1x,cp1y為控制點(diǎn)一,cp2x,cp2y為控制點(diǎn)二。
下邊的圖能夠很好的描述兩者的關(guān)系,二次貝塞爾曲線有一個(gè)開始、結(jié)束點(diǎn)(藍(lán)色)以及一個(gè)控制點(diǎn)(紅色),而三次貝塞爾曲線使用兩個(gè)控制點(diǎn)。
參數(shù)x、y在這兩個(gè)方法中都是結(jié)束點(diǎn)坐標(biāo)。cp1x,cp1y為坐標(biāo)中的第一個(gè)控制點(diǎn),cp2x,cp2y為坐標(biāo)中的第二個(gè)控制點(diǎn)。
使用二次以及三次貝塞爾曲線是有一定的難度的,因?yàn)椴煌谙馎dobe Illustrators這樣的矢量軟件,我們所繪制的曲線沒(méi)有直接的視覺反饋給我們。這讓繪制復(fù)雜的圖形十分的困難。在下面的例子中,我們會(huì)繪制一些簡(jiǎn)單有規(guī)律的圖形,如果你有時(shí)間,以及更多的耐心很多復(fù)雜的圖形你都可以繪制出來(lái)。
可以看我自己寫的一個(gè)實(shí)際項(xiàng)目例子,在我的文章里有。
今天就先寫到這了。后面再慢慢給大家寫,我也是剛剛學(xué)這個(gè)。不足之處多諒解。關(guān)注我哦^_^!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/49952.html
摘要:二次以及三次貝塞爾曲線都十分有用,一般用來(lái)繪制復(fù)雜有規(guī)律的圖形。繪制三次貝塞爾曲線,為結(jié)束點(diǎn),為控制點(diǎn)一,為控制點(diǎn)二。下邊的圖能夠很好的描述兩者的關(guān)系,二次貝塞爾曲線有一個(gè)開始結(jié)束點(diǎn)藍(lán)色以及一個(gè)控制點(diǎn)紅色,而三次貝塞爾曲線使用兩個(gè)控制點(diǎn)。 元素 看起來(lái)和 元素很相像,唯一的不同就是它并沒(méi)有 src 和 alt 屬性。實(shí)際上, 標(biāo)簽只有兩個(gè)屬性—— width和height。當(dāng)沒(méi)有...
摘要:二次以及三次貝塞爾曲線都十分有用,一般用來(lái)繪制復(fù)雜有規(guī)律的圖形。繪制三次貝塞爾曲線,為結(jié)束點(diǎn),為控制點(diǎn)一,為控制點(diǎn)二。下邊的圖能夠很好的描述兩者的關(guān)系,二次貝塞爾曲線有一個(gè)開始結(jié)束點(diǎn)藍(lán)色以及一個(gè)控制點(diǎn)紅色,而三次貝塞爾曲線使用兩個(gè)控制點(diǎn)。 元素 看起來(lái)和 元素很相像,唯一的不同就是它并沒(méi)有 src 和 alt 屬性。實(shí)際上, 標(biāo)簽只有兩個(gè)屬性—— width和height。當(dāng)沒(méi)有...
摘要:以上代碼功能很簡(jiǎn)單,就是把定義為一個(gè)模塊,在中引用,最終兩文件中要添加的內(nèi)容都顯示在中。我們的任務(wù)完成了,成功生成,合并,引入了,被執(zhí)行了。安裝,處理文件。 前言: 本套教程是零基礎(chǔ)學(xué)打包工具webpack; 后面會(huì)結(jié)合gulp+webpack搞定所有你得需求; 閑談: 百度搜了一下,雖然教程多,但是雜亂無(wú)章,實(shí)用的沒(méi)多少,都是匆匆了事,所以我就自己學(xué)了兩天,現(xiàn)在從最底層教大家完成we...
摘要:以上代碼功能很簡(jiǎn)單,就是把定義為一個(gè)模塊,在中引用,最終兩文件中要添加的內(nèi)容都顯示在中。我們的任務(wù)完成了,成功生成,合并,引入了,被執(zhí)行了。安裝,處理文件。 前言: 本套教程是零基礎(chǔ)學(xué)打包工具webpack; 后面會(huì)結(jié)合gulp+webpack搞定所有你得需求; 閑談: 百度搜了一下,雖然教程多,但是雜亂無(wú)章,實(shí)用的沒(méi)多少,都是匆匆了事,所以我就自己學(xué)了兩天,現(xiàn)在從最底層教大家完成we...
閱讀 2285·2021-11-15 11:37
閱讀 2954·2021-09-01 10:41
閱讀 787·2019-12-27 11:58
閱讀 747·2019-08-30 15:54
閱讀 715·2019-08-30 13:52
閱讀 2930·2019-08-29 12:22
閱讀 1075·2019-08-28 18:27
閱讀 1452·2019-08-26 18:42