上文我們講到了畫一條線,畫矩形,寫文字,總算是有了一個好的開頭,如果還沒看的同學出門左轉,先看看那篇,這裡就不多做敘述了,接下來我們來看比較複雜的一些屬性和方法!
講之前呢,我還是想溫習一下,畢竟上文還有幾個屬性沒講到,那我們從畫三角形開始吧!
如果看了上文,機智的少年一定會想到,三角形,多簡單啊,無非是比直線多一個點,於是這少年就開始動手了:
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); ctx.moveTo(50,50); ctx.lineTo(100,100); ctx.lineTo(50,200); ctx.stroke();
呀呵,怎麼是折線,三角形不是只有三個點嗎?是不是因為沒有閉合呢?那我再加一點:
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); ctx.moveTo(50,50); ctx.lineTo(100,100); ctx.lineTo(50,200); ctx.lineTo(50,50); ctx.stroke();
哈哈,果然機智如你!這個想法其實是正解的,三角形就是這麼簡單,其實還有一種方式可以畫三角形,只需3個點,那就是我們要介紹的:
closePath()閉合路徑
有閉合就是開始,一般來說他們是成雙成對的
beginPath()開始路徑
這對活寶的用法一般是:
ctx.beginPath(); ctx.closePath();
先開始路勁,裡面寫你要繪製的內容,然後結束路勁,相當於是一個盒子已經封箱了,這樣做有個好處就是可以避免繪製過程中的樣式污染,你不知道怎麼污染?好吧,看下面:
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); //第一个三角 ctx.strokeStyle='red'; ctx.moveTo(50,50); ctx.lineTo(100,100); ctx.lineTo(50,200); ctx.lineTo(50,50); ctx.stroke(); //第二个三角 ctx.strokeStyle='green'; ctx.moveTo(150,50); ctx.lineTo(200,100); ctx.lineTo(150,200); ctx.lineTo(150,50); ctx.stroke();
如圖,如果我本來是想讓第一個三角形的顏色為紅色,第二個為綠色,但是現在的結果卻都是綠色,而且眼尖的同學還看到,第一個三角感覺有2個顏色,顏色也特別的深,感覺疊了2個三角,你沒看到?好,我們改改,你在看:
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); //第一个三角 ctx.strokeStyle='red'; ctx.moveTo(50,50); ctx.lineTo(100,100); ctx.lineTo(50,200); ctx.lineTo(50,50); //ctx.stroke(); //第二个三角 ctx.strokeStyle='green'; ctx.moveTo(150,50); ctx.lineTo(200,100); ctx.lineTo(150,200); //ctx.lineTo(150,50); ctx.stroke();
我們先不畫第一個三角,也不畫第二個三角的左邊一邊,然後看一下:
第一個三角沒有雙重色了,說吧畫了2次,一次紅,一次綠,去掉了重繪,後面的顏色也將前面的顏色污染了,這不是我們想要的,這污染,你應該明白了吧!
那我們用那對活寶看看:
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); //第一个三角 ctx.beginPath(); ctx.strokeStyle='red'; ctx.moveTo(50,50); ctx.lineTo(100,100); ctx.lineTo(50,200); ctx.lineTo(50,50); ctx.closePath(); ctx.stroke(); //第二个三角 ctx.beginPath(); ctx.strokeStyle='green'; ctx.moveTo(150,50); ctx.lineTo(200,100); ctx.lineTo(150,200); ctx.lineTo(150,50); ctx.closePath(); ctx.stroke();
這才是我們想要的嘛,你玩你的,我玩我的,互不干擾,(你說畫三角只要3個點的呢,吹牛B吧,你看你都是用的4個點),哦,對。
closePath()方法建立從目前點到起始點的路徑,這是對此方法的描述,也就是說,使用這個方法,就能將畫筆移到beginPath()的位置,這樣才能結束畫布,所以照這個理論,當畫三角時,畫到第三個點時,我們用closePath()方法讓畫筆回到起點,再畫線,是不是就閉合了,看看效果:
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); ctx.beginPath(); ctx.strokeStyle='red'; ctx.moveTo(50,50); ctx.lineTo(100,100); ctx.lineTo(50,200); ctx.closePath(); ctx.stroke();
看,只有三個點,不是折線吧,後面要講的什麼扇形圖,不規則圖形都可以用此技能,妥妥的!
嗨,也不過如此,你這線條都是一像素的,又不能跟孫悟空的金箍棒一樣,要大變大,要小變小,哼,誰說的,哥有神器在手,天下無敵!
我的法寶是:
lineWidth設定或返回目前的線條寬度
怎麼用?哥給一個跟金箍棒:
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); vartimer=null; varnum=1; ctx.moveTo(150,50); ctx.strokeStyle='gold'; setInterval(function(){ if(num==100){ clearInterval(timer); num=1; }else{ num++; }; ctx.lineTo(150,100+num*2); ctx.lineWidth=num; ctx.stroke(); },100)
金色箍棒,大,大,大,大,在大點,哈哈哈~~~
咳咳,嚴肅點,有此神器,我們就可以修改任何線框,線條的線條寬度了,比如說空心三角形,空心矩形,當然,空心文字你就不要問我了,我不知道~
關於線條,還有另外2個屬性:
lineJoin兩線交叉的角落類型
參數:
miter:尖角預設
bevel:斜角
round:圓角
什麼意思,那就用空心矩形為例:
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); ctx.lineWidth=10; ctx.beginPath(); ctx.lineJoin='miter'; ctx.strokeRect(100,10,80,80); ctx.closePath(); ctx.beginPath(); ctx.lineJoin='round'; ctx.strokeRect(100,110,80,80); ctx.closePath(); ctx.beginPath(); ctx.lineJoin='bevel'; ctx.strokeRect(100,210,80,80); ctx.closePath();
右側為折線效果
配合折線效果,還有一個屬性:
miterLimit規定最大斜接長度。什麼意思?看看右邊的這個折線圖,最下面那組的尖尖角,這個就是斜接,意思通俗意思就是規定那個尖尖角的長度,如果尖尖角的長度小於miterLimit的值,則正常顯示,如果大於的話,就會被截掉一部分,其形狀就跟lineJoin='bevel'一樣一樣的,且此方法只對lineJoin="miter"預設值的時候才起作用,給個形象的例子吧:
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); ctx.lineWidth=10; ctx.lineJoin="miter"; ctx.beginPath(); ctx.miterLimit=19; ctx.moveTo(20,20); ctx.lineTo(150,27); ctx.lineTo(20,34); ctx.stroke(); ctx.beginPath(); ctx.miterLimit=18; ctx.moveTo(20,120); ctx.lineTo(150,127); ctx.lineTo(20,134); ctx.stroke();
ctx.beginPath(); ctx.lineJoin="bevel"; ctx.moveTo(20,220); ctx.lineTo(150,227); ctx.lineTo(20,234); ctx.stroke();
如圖,當miterLimit的值大於等於19時,尖尖角正常顯示,小於18時,尖尖角被截斷了,效果跟設定lineJoin='bevel'是一樣的,暫不知道會有什麼作用,待以後來發掘!
另一個:
lineCap設定或傳回線條的結束端點樣式註意,這是設定線條的哦!
參數:
butt預設。在線條的每個末端添加平直的邊緣。
round在線條的每個末端加上圓形線帽。
square在線條的每個末端加上正方形線帽。
什麼意思?線條嘛,我們還是以金箍棒為例,算了,還是用線條吧(看到金箍棒我就想笑了);
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); ctx.lineWidth=10; ctx.beginPath(); ctx.lineCap='butt'; ctx.moveTo(50,50); ctx.lineTo(200,50); ctx.stroke(); ctx.beginPath(); ctx.lineCap='round'; ctx.moveTo(50,100); ctx.lineTo(200,100); ctx.stroke(); ctx.beginPath(); ctx.lineCap='square'; ctx.moveTo(50,150); ctx.lineTo(200,150); ctx.stroke();
可以看到,後面2個比第一個要長一點,具體長多少呢?畫一張圖示意一下:
圆角和方脚的原理其实是这样的,很明显多出的一部分的宽度就是线条的一半的长度,所以要精确计算其长度,此小细节需谨记!
现在我们来讲讲画圆及其相关的图形:
arc(x,y,r,sAngle,eAngle,counterclockwise)
什么意思?x,y表示坐标点表示圆心坐标,r表示半径,sAngle表示开始弧度,eAngle表示结束弧度,counterclockwise表示顺时针还是逆时针方式,默认为顺时针false,逆时针为true
注意,这里的角度是用弧度表示的,不是直接写角度,那问题来了,一般我们知道一个圆弧是多少度,怎么知道它是多少弧度呢?总感觉弧度太抽象,嗯嗯,我也有同感,那我们就来科普一下弧度的算法吧,列几个公式(初中,高中的数学,都还给老师了):
1弧度=r;
360°=2∏;
周长C=2∏r;
那么一周的弧度数=2∏r/r=2∏=360°
则1°=2∏*1°/360°=∏*1°/180°(弧度)
90°=∏*90°/180°(弧度)
圆的初始位置是在最右边,跟我们自己手绘圆的起点有那么一点点的不一样,默认是顺时针方向,那角度就应该是如图所示的角度,要是还不清楚的话,我们画2半圆,分别表示顺时针和逆时针,这样就应该清楚了,哦,需要说明的一点就是,画用的方法跟画直线和矩形框的原理是一样的,只是画出了路径,并没有添墨水,仍需用黑白双煞:
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); ctx.beginPath(); ctx.arc(80,100,50,0,180*Math.PI/180,false); ctx.stroke(); ctx.beginPath(); ctx.arc(200,100,50,0,180*Math.PI/180,true); ctx.stroke();
js里面是没有∏的,你懂的,但是有函数Math.PI,咦,这里为什么是圆弧而不是半圆啊,如果我要画一个半圆怎么弄呢?哈哈~,还记得上面三角形的那个折线吗?这个是一个原理,只是图形没有闭合而已,用closePath()就可以闭合了。
画一个扇形看看,这里我就闭合图形哈:
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); ctx.beginPath(); ctx.arc(80,100,50,30*Math.PI/180,150*Math.PI/180,false); ctx.closePath(); ctx.stroke();
当当当当~~~噗,喷了一口老血,怎么是一条小船,说好的扇子呢?再看看三角图形,瞬间就明白了,图形闭合不是以圆心为起始点的,而是初始弧度为起点,然后闭合的时候是回到初始点,就变成小船了,那怎么才能画出一个扇形呢?给个思路,这里暂时不给代码,以后有时间当小实例给到大家,如果我以圆心为起点,画2条直线,连到圆弧的起始点和结束点,是不是就是一个扇形了,哈哈~,不多说了,脑补一下吧,当然,圆弧的起始点的坐标和结束点的坐标计算还是有点费劲的
前面我们画的是空心的圆或弧,可否画实心的呢?貌似问的有点多余,上面说了用黑白双煞,好吧,直接给个一饼好了:
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); ctx.arc(150,150,50,0,360*Math.PI/180,false); ctx.fill();
咦,怎么这么像某岛国国旗,还好我用的是默认黑色,嘘嘘,都没看到哈~
还有一个方法可以画圆弧:
arcTo(x1,y1,x2,y2,r)创建两个切线之间的弧/曲线
参数:x1,y1表示第一个坐标,x2,y2表示第二个坐标,r表示曲线半径
两个切线之间的曲线,试试:
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); ctx.beginPath(); ctx.moveTo(20,20); ctx.lineTo(100,20); ctx.arcTo(150,20,150,70,50); ctx.lineTo(150,120); ctx.stroke();
果然是要在两条线段之间写曲线,要是先写2条曲线,在写arcTo(),貌似就出不来了,这让我们想到了moveTo(),lineTo(),再写一个例子:
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); ctx.moveTo(150,20); ctx.arcTo(150,200,50,0,20); ctx.stroke();
想试一下,要是只有一条切线,会怎样?
好大的一个鱼钩啊,看来这样也是可以的,要是没有切线,可否?
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); ctx.arcTo(150,200,50,0,20); ctx.stroke();
额,狗带了,没反应,看来必须至少有一个切线才能画弧线,有个点都行,要求不算高,满足你。
感觉这里始终没有将清楚,arcTo()为什么会画出这样的曲线呢,我觉得有必要画一张图来表示:
它的绘图原理应该是这样的,起始点是圆弧的第一个切点,也是画笔的起始点,然后arcTo的两个坐标点分别是圆弧的起点和终点,这样3个点就形成了2天相交的线,然后以半径为r画一个圆,与这2条线相切,2个切点就是绘制的这条弧,而第二张图就是arcTo()所绘制的图形,为了证实这一点,我们写一个相近的图形来看看:
varcanvas=document.getElementById("canvas"); varctx=canvas.getContext("2d"); ctx.beginPath(); ctx.fillRect(100,100,5,5); ctx.fillRect(180,80,5,5); ctx.fillRect(160,180,5,5); ctx.moveTo(62,112); ctx.lineTo(182,82); ctx.lineTo(162,182); //这里是绘制切线弧 ctx.moveTo(103,103); ctx.arcTo(183,83,162,182,40); ctx.stroke();
对比这2组图,将生成的弧线用圆对比一下,会发现起点并不是切点,但基本思路是正确的,3点形成一个夹角,然后以r为圆心,画一个圆,从起点到第二个切点,就是arcTo()方法所绘制的图形。
今天就到这吧!讲的很混乱,东一脚西一脚的,希望你们能懂!最希望的是能对你们有帮助,那就再好不过了!
以上就是canvas API ,通俗的canvas基础知识(二) 的内容,更多相关内容请关注PHP中文网(m.sbmmt.com)!
相关文章: