what is canvas?(什么是canvas)
其實他只是H5里面的一個標簽而已,那么他作為一個標簽,肯定有他的用途,他就像是一幅畫布,等待着你來作畫。可以說,他只是一個容器而已,需要配合着JavaScript來進行繪制。
那么他能做些什么東西呢?
例如這個:http://www.yyyweb.com/demo/tearable-cloth/index.html
還有這個:http://canvasrider.com/tracks/409068
用處很多,但是用的最多的還是,簡單的畫個圖形啊,圖形移動 什么的。
那么開始介紹它的怎么使用的:
創建標簽,那么畫布的大小設置,在標簽上面設置,如果在css設置,設置的是這個標簽的大小,而不是畫布的大小,這點要注意。
<canvas width="500px" height="500px"></canvas>
<canvas width="500px" height="500px" style="border: 1px solid"></canvas>
加上邊框,以便於我們知道他在哪里,下面的框框,就是畫布的區域了
<body>
<canvas id="can" width="500px" height="500px" style="border: 1px solid"></canvas>
<script>
var can = document.getElementById('can'); //選擇canvas標簽
var ctx = can.getContext('2d'); //選擇畫布的繪制的類型,只能填2d
</script>
</body>
開始畫出我們的第一條線。
<script>
var can = document.getElementById('can'); var ctx = can.getContext('2d'); ctx.moveTo(100,100); // 選擇在畫布中的起始位置, 左上角是0,0
ctx.lineTo(200,200); // 選擇從起始位置開始,畫到 200 200 的位置
ctx.stroke(); // 開始畫。
</script>
<script>
var can = document.getElementById('can'); var ctx = can.getContext('2d'); ctx.moveTo(100,100); ctx.lineTo(200,200); ctx.lineTo(0, 200); //再添加一條線 ctx.stroke();
</script>
效果圖如下:
接下來,閉合他形成一個三角形
<script>
var can = document.getElementById('can'); var ctx = can.getContext('2d'); ctx.moveTo(100,100); ctx.lineTo(200,200); ctx.lineTo(0, 200); ctx.closePath();//閉合圖形,有兩條線以上的,能自動幫你連接到 起始點。
// ctx.lineTo(100,100);當然自己計算位置,也是可以的
ctx.stroke(); </script>
效果圖如下: 一個三角形的形狀就出來了。
上面是畫直線,下面畫曲線。畫曲線呢,需要用到二次貝賽爾曲線,和三次貝賽爾曲線。
二次貝塞爾曲線呢,有三個點。起始點,控制點,和終點。首先,現象一個常見。 有一條繩子,頭尾固定,在中間再綁一條繩子,往上拉。 就像下面這樣
所以 中間那個點,如果越高,那么 就會越彎曲。
那么還有個三次貝塞爾曲線,聽名字就知道,比二次貝賽爾曲線多了 一個點。bezierCurveTo()
畫矩形呢,不需要一步一步的畫,有方法,直接可以畫 cxt.rect(x,y,width,height)
<script>
var can = document.getElementById('can'); var ctx = can.getContext('2d'); ctx.rect(50, 50, 200, 100); //第一二個參數是 起始點的X,Y,第三四個參數是 矩形的寬高
ctx.stroke(); //開始畫
</script>
效果如下:
不過,不止有一個方法而已, 還有另外兩個方法:
<script>
var can = document.getElementById('can'); var ctx = can.getContext('2d'); ctx.strokeRect(50, 50, 200, 100); //第一二個參數是 起始點的X,Y,第三四個參數是 矩形的寬高
//不用寫 ctx.stroke();
</script>
這個方法的,雖然也是畫矩形,只不過他會填充顏色。
<script>
var can = document.getElementById('can'); var ctx = can.getContext('2d'); ctx.fillRect(50, 50, 200, 100); //第一二個參數是 起始點的X,Y,第三四個參數是 矩形的寬高
</script>
接下來,畫圓。arc(100,100,50,0,Math.PI *2, 0), 第一二個參數,還是起始點的位置X,和Y。 只不過起始點是在圓心。第三個參數是,圓的半徑,第四五個參數,是起始弧度的位置,和結束的位置, 最后一個參數,是以順時針,還是逆時針畫 0為順時針,1為逆時針。
那我們設置, 第四個參數,為0, 第五個參數為360度,也就是 Math.PI * 2。 是不是就是一個圓啦。
<script>
var can = document.getElementById('can'); var ctx = can.getContext('2d'); ctx.arc(100, 100, 50, 0, Math.PI *2, 0); ctx.stroke(); </script>
還有一個注意點,順時針的,90度,和逆時針的90度,是不一樣的呢。
ctx.arc(100, 100, 50, 0, Math.PI *0.5, 0); ctx.arc(300, 100, 50, 0, Math.PI *0.5, 1);
再畫個圓角矩形。需要用到arcTo()方法,首先,我們需要知道幾個點的位置 ↓
arcTo(150, 20, 150, 30, 50)呢,有5個參數, 第一二個參數,是決定了 B點的位置,第三個四個參數呢,是決定了 怎么彎,往上彎,還是往下彎。 第五個參數呢,是圓角的像素,像border-radius 屬性一樣。
第一步,決定A點,使用moveTo(20, 20)。
ctx.moveTo(20, 20);
第二步,決定B點的位置。
ctx.arcTo(150, 20, , , ,);
第三步,往上彎,還是往下彎(這個屬性怎么決定呢? 第三個參數,可以理解為X,B點的X為150,你如果要往上下彎的話,那么第三個參數,就要跟B點的X 一樣。 也就是150,
關鍵在第四個值,第四個參數,是Y,如果要往下彎的話,那么Y的值,就要大於 B點的Y值, 如果要往上彎的話,就要小於B點的Y值。 大多少小多少無所謂,只要大過就行)
ctx.arcTo(150, 20, 150, 30, );
第四步,決定角度的程度
ctx.arcTo(150, 20, 150, 30, 50);
第五步,畫出來
ctx.stroke();
效果圖:
如果要往上彎呢,第四個參數要小於 B點的Y 對吧。那么我們把代碼改成 ctx.arcTo(150, 20, 150, 10, 50); 第四個參數 10, 比B點的Y 20 小。所以會變成往上彎。
記住一點就行。(如果要往上下彎,改變Y,往左右彎,改變X)
那么接下來,畫個完整的圓角矩形。
這是我們上面教的。 到這里應該怎么辦了呢。 計算出 A點的 X 和 Y等於200,80
最后一個點。
最后,會發現,出了一條線。 我們只需要把起始點的X +20 即可。為啥+20? 因為 彎曲的值為 20。
其實他還不止可以填充單色。還可以填充線性漸變,徑向漸變。
線性漸變:

因為,漸變開始的點,是X0,Y0, 並不是圖形的 左上角那個點,而是畫布的左上角 (原點) 所以,你把圖形的位置移動一下。你就會發現 問題了。
有沒有想過一個問題,如果內圈的圓,超過外面的圓會成什么樣子?
如果兩個圈,相等且相離呢?
話說,為什么會出現這種情況呢? 其實最主要的一點還是,他的原理,下面是一張原理示意圖:
現在,我們會畫單個圖形了,如果要畫多個圖形,或者,多條線,不相連呢?因為我們知道,我們的每一筆操作,都是連在一起的。
有個方法。ctx.beginPath()。 可以把它理解為,我把筆拿起來。具體下個位置在哪里。需要再次 重新定起始點。
如果不把筆拿起來會怎么樣呢? ↓ 像寫連筆字一樣,不會中斷的。
如果要畫兩個圖形,或者 不連在一起的話,需要使用beginPath() 方法。可以重新 設置起始點。
縮放ctx,scale(1, 1); 1是默認值,正常大小。 小於1 也就是 0~0.99 都是縮小, 大於1呢 2是2倍, 3是3倍。如此類推
平移。ctx.translate(100, 100);
旋轉。ctx.rotate(Math.PI) 一個PI 等於180度,以畫布原點旋轉,而不是以自身的左上角旋轉。
如果要把旋轉點,在圖形上面,是用translate 進行平移原點即可。
那么 縮放,平移,旋轉,都是按照原點進行的,后續的操作,都會受到 原點的移動,而發生錯位,什么的。 所以canvas 還有一個方法,就是用來存儲數據的。
那么,如何不受到影響呢? 使用ctx.save() 方法進行存儲 畫布原點的位置。
那么 save 能存儲什么呢? 他能存儲 translate rotate scale 的值。 因為這些改變,都是全局的。
還有另外一種填充圖片的方法:
drawImage方法,可選參數:
陰影效果
最后,補充:
改變線的粗細
改變線的顏色
改變線起始與結尾的樣式
改變線於線之間的連接點樣式