本文首發地址: 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函數可以繪製圓形,同樣也可以繪製弧線。
除了給定圓心座標和半徑之外,還要給定繪製的弧度(包括起始角度和結束角度),我們要繪製圓形,所以給定0
和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():結束繪畫
這樣就可以完整的開始繪圖了,小夥伴們多多練習。