本文首發位址: https://www.jeremyjone.com/465/ ,轉載請注明
代碼位址:https://github.com/jeremyjone/CanvasPaint ,需要請自行檢視。
在JavaScript 之 canvas(一)中了解了canvas的繪圖原理,這次就開始繪制基本圖形。
一般來說,canvas的圖形分成實心(fill)和空心(stroke),我們的繪圖闆基本使用的是空心圖形,但是也要了解一下實心圖形,其原理是一毛一樣的。
直線
一般來說,直線需要知道兩端坐标,是以代碼如下:
// 直線
context.moveTo(150, 150); // 移動到某一位置
context.lineTo(300, 150); // 畫直線從目前點到給定的位置
context.stroke();
這樣就繪制出一條起點在 (150, 150),終點在 (300, 150) 的水準直線。
好像很簡單的樣子,接着來看下一個。
箭頭
箭頭的思路和直線差不多,先畫直線,然後在終點位置畫一個填充的三角形即可。
注意三角形需要按照直線的方向,是以用到的數學屬性如下:
// 箭頭
// 箭頭的思路和直線差不多,先畫直線,然後在終點位置畫一個填充的三角形即可
// 注意三角形需要按照直線的方向,是以用到的數學屬性如下
context.moveTo(230, 230); // 移動到指定坐标
context.lineTo(500, 230); // 畫直線
context.stroke(); // 填充直線
let endRadians = Math.atan((230 - 230) / (500 - 230)); // 計算出目前直線的角度
endRadians += ((500 >= 230) ? 90 : -90) * Math.PI / 180; // 角度的正負取值
context.translate(500, 230); // 使用translate函數轉換坐标系,将該坐标重新定義為原點
context.rotate(endRadians); // 把該直線看做水準坐标(目的是讓整個canvas沒有角度,友善計算)
// 下面就是根據直線終點繪制三角箭頭,并填充三角形
context.moveTo(0, -2 * context.lineWidth);
context.lineTo(2 * context.lineWidth, 3 * context.lineWidth);
context.lineTo(-2 * context.lineWidth, 3 * context.lineWidth);
context.fillStyle = context.strokeStyle;
context.fill();
裡面具體的參數小夥伴可以自行修改,具體的實作思路,我已經寫在代碼中的注釋部分,應該還算詳細。
這樣就得到一個如下圖的圖檔:
顔色我重新調整了,友善截圖,第一講中已經說過顔色的調整,這裡就不贅述。
繼續下一個圖形。
矩形
基本圖形剛才已經說過,分為實心和空心,先來看實心矩形,上代碼:
// 矩形
// 使用fillRect函數,(起點x,起點y,終點x,終點y), 顔色為fillStyle給定的顔色
context.fillRect(50, 50, 150, 150);
一行代碼就能夠得到一個實心矩形。
那麼空心矩形如下:
// 空心矩形
// 使用strokeRect函數,坐标參數與矩形一緻,顔色為strokeStyle給定的顔色,畫筆粗細為lineWidth的值
context.strokeRect(100, 100, 200, 200);
這兩個矩形同時顯示效果如下,注意後面的代碼永遠在上面展示:
矩形介紹完,該介紹圓形,更加簡單。
圓形
圓形同樣一個函數就可以搞定:
// 圓形
// 使用arc函數,(圓心x,圓心y,半徑,起始角度,結束角度,[可選參數:順時針false/逆時針true])
let r = 50; // 半徑
context.arc(200, 200, r, 0, Math.PI * 2); // 繪制圓
context.fill(); // 填充
context.stroke(); // 描邊
這裡面稍微有個不太好了解的地方,參數比想象的要多一些。起始arc函數可以繪制圓形,同樣也可以繪制弧線。
除了給定圓心坐标和半徑之外,還要給定繪制的弧度(包括起始角度和結束角度),我們要繪制圓形,是以給定
和
Math.PI * 2
,這樣才能繪制一個完整的圓形。
在w3c網站上我找到這張解釋圖檔,還是比較清晰明了:
根據最後一個可選參數(false為順時針,也是預設值,true為逆時針),就可以繪制出對應的弧線。
最後兩行代碼,如果需要空心圓,使用
stroke()
描邊即可。如果需要實心圓,使用
fill()
填充即可。
那麼基本的圖形就說完了,貼上完整代碼:
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var context = canvas.getContext("2d"); //2d用引用括起來
}
// 檢測浏覽器是否支援canvas 該方法是否存在 取得上下文對象
if (canvas.getContext) {
var context = canvas.getContext('2d'); //2d用單引用括起來
if (canvas.getContext) {
context.fillStyle = "red"; // 填充顔色為紅色
context.strokeStyle = "blue"; // 畫筆的顔色
context.lineWidth = 5; // 指定描邊線的寬度
// 儲存目前狀态,開始繪圖
context.save();
context.beginPath();
// 直線
context.moveTo(150, 150); // 移動到某一位置
context.lineTo(300, 150); // 畫直線從目前點到給定的位置
context.stroke();
// 箭頭
// 箭頭的思路和直線差不多,先畫直線,然後在終點位置畫一個填充的三角形即可
// 注意三角形需要按照直線的方向,是以用到的數學屬性如下
context.moveTo(230, 230); // 移動到指定坐标
context.lineTo(500, 230); // 畫直線
context.stroke(); // 填充直線
let endRadians = Math.atan((230 - 230) / (500 - 230)); // 計算出目前直線的角度
endRadians += ((500 >= 230) ? 90 : -90) * Math.PI / 180; // 角度的正負取值
context.translate(500, 230); // 使用translate函數轉換坐标系,将該坐标重新定義為原點
context.rotate(endRadians); // 把該直線看做水準坐标(目的是讓整個canvas沒有角度,友善計算)
// 下面就是根據直線終點繪制三角箭頭,并填充三角形
context.moveTo(0, -2 * context.lineWidth);
context.lineTo(2 * context.lineWidth, 3 * context.lineWidth);
context.lineTo(-2 * context.lineWidth, 3 * context.lineWidth);
context.fillStyle = context.strokeStyle;
context.fill();
// 矩形
// 使用fillRect函數,(起點x,起點y,終點x,終點y), 顔色為fillStyle給定的顔色
context.fillRect(50, 50, 150, 150);
// 空心矩形
// 使用strokeRect函數,坐标參數與矩形一緻,顔色為strokeStyle給定的顔色,畫筆粗細為lineWidth的值
context.strokeRect(100, 100, 200, 200);
// 圓形
// 使用arc函數,(圓心x,圓心y,半徑,起始角度,結束角度,[可選參數:順時針false/逆時針true])
let r = 50; // 半徑
context.arc(200, 200, r, 0, Math.PI * 2); // 繪制圓
context.fill(); // 填充
context.stroke(); // 描邊
// 還原狀态,結束目前繪畫
context.restore();
context.closePath();
}
}
可以看到在繪制之前使用了
save()
和
beginPath()
函數,作用如下:
- save():儲存目前繪制狀态,比如畫筆粗細,顔色等資訊
- beginPath():開始繪畫
同時在結尾使用了
restore()
和
closePath()
函數,作用如下:
- restore():還原之前的畫筆狀态
- closePath():結束繪畫
這樣就可以完整的開始繪圖了,小夥伴們多多練習。