JavaScript 之 canvas(二)-- 繪製基本圖形

本文首發地址: 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();

file

這樣就繪製出一條起點在 (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();

裏面具體的參數小夥伴可以自行修改,具體的實現思路,我已經寫在代碼中的註釋部分,應該還算詳細。

這樣就得到一個如下圖的圖片:

file

顏色我重新調整了,方便截圖,第一講中已經說過顏色的調整,這裏就不贅述。

繼續下一個圖形。

矩形

基本圖形剛纔已經說過,分爲實心和空心,先來看實心矩形,上代碼:

// 矩形
// 使用fillRect函數,(起點x,起點y,終點x,終點y), 顏色爲fillStyle給定的顏色
context.fillRect(50, 50, 150, 150);

一行代碼就能夠得到一個實心矩形。

那麼空心矩形如下:

// 空心矩形
// 使用strokeRect函數,座標參數與矩形一致,顏色爲strokeStyle給定的顏色,畫筆粗細爲lineWidth的值
context.strokeRect(100, 100, 200, 200);

這兩個矩形同時顯示效果如下,注意後面的代碼永遠在上面展示:
file

矩形介紹完,該介紹圓形,更加簡單。

圓形

圓形同樣一個函數就可以搞定:

// 圓形
// 使用arc函數,(圓心x,圓心y,半徑,起始角度,結束角度,[可選參數:順時針false/逆時針true])
let r = 50;  // 半徑
context.arc(200, 200, r, 0, Math.PI * 2);  // 繪製圓
context.fill();  // 填充
context.stroke();  // 描邊

這裏面稍微有個不太好理解的地方,參數比想象的要多一些。起始arc函數可以繪製圓形,同樣也可以繪製弧線。
除了給定圓心座標和半徑之外,還要給定繪製的弧度(包括起始角度和結束角度),我們要繪製圓形,所以給定0Math.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():結束繪畫

這樣就可以完整的開始繪圖了,小夥伴們多多練習。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章