天天看點

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();
           
JavaScript 之 canvas(二)-- 繪制基本圖形

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

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

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

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

顔色我重新調整了,友善截圖,第一講中已經說過顔色的調整,這裡就不贅述。

繼續下一個圖形。

矩形

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

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

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

那麼空心矩形如下:

// 空心矩形
// 使用strokeRect函數,坐标參數與矩形一緻,顔色為strokeStyle給定的顔色,畫筆粗細為lineWidth的值
context.strokeRect(100, 100, 200, 200);
           

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

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

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

圓形

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

// 圓形
// 使用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網站上我找到這張解釋圖檔,還是比較清晰明了:

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

根據最後一個可選參數(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():結束繪畫

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

繼續閱讀