五分鐘學會 Canvas 基礎(二)

請各位讀者添加一下作者的微信公眾號,以后有新的文章,將在微信公眾號直接推送給各位,非常感謝。


0. 前言

相信各位小伙伴讀了之前的文章,對 Canvas 基礎已經有了一定的認識和了解,但是大家也一定記得我在上一篇文章留了一個小的坑。

就是我沒有告訴大家該如何去繪制圓,之所以沒有說是因為繪制圓實際上是因為 CanvasRenderingContext2D 對象只提供了兩個繪制矩形的方法,并沒有直接提供繪制圓,橢圓等幾何圖形的方法。為了在 Canvas 上繪制更復雜的方法,必須在 Canvas 上啟用路徑,借用路徑來繪制圖形。

那么我們現在就一起來看一看,該如何使用路徑來繪制圓等圖形吧。

------------------我是華麗的分割線----------------------

下一篇文章預告, canvas 的各種圖像特效。

另外,接下來一段時間,小編要享受一下假期,暫時不會給各位讀者老爺更新啦,希望各位老爺耐心等待。

1.使用路徑

在 Canvas 上使用路徑,可按照下面的步驟進行。

  1. 調用 CanvasRenderingContext2D 對象的 beginPath()方法開始定義路徑。
  2. 調用CanvasRenderingContext2D 的各種方法添加子路徑。
  3. 調用CanvasRenderingContext2D 的 closePath 方法關閉路徑。
  4. 調用CanvasRenderingContext2D 的fill()或 stroke()方法來填充路徑或者繪制路徑邊框。

那我們明確了該如何去進行應該怎么去使用路徑,那么我們接下來就來介紹一下 canvas 中添加子路徑的方法。

- -
arc(float x,float y,float radius,float startAngle,float endAngle,boolean counterclockwise) 向 canvas 的當前路徑上添加一段弧。繪制以 x , y 為圓心,radius 為半徑,從 startAngle 角度開始,到 endAngle 角度結束的圓弧。startAngle 和 endAngle 以角度為單位。
arcTo(float x1,float x2,float y1,float y2,float radius) 向 canvas 的當前路徑上添加一段弧。與上一個方法不同的地方只是定義弧的方式不同。
bezierCurveTo(float cpX1, float cpY1, float cpX2, float cpY2, float x, float y) 在當前路徑上添加一段貝塞爾曲線
quadraticCurveTo(float cpX, float cpY,float x,float y) 向 canvas 當前路徑添加一段二次貝塞爾曲線
rect(float x, float y,float width, float height) 向 canvas 的當前路徑上添加一個矩形

方法就這些,但是參數就顯得非常多了,咱們來一條條的來看看這些方法的具體使用吧。

1.1 繪制圓

首先我們來學習下如何繪制圓,首先明確,我們應該去使用 arc ( ) 方法,那么我們該如何去使用這個方法呢?

咱們,放“碼”過來。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div>
        <h2>繪制圓形</h2>
        <canvas id="canvas_1" width="1000" height="500" style="box-shadow: 0px 0px 20px black;">
            當前瀏覽器不支持 canvas
        </canvas>
    </div>
</body>
<script type="text/javascript">
    // 獲取 canvas 元素對應的 DOM 對象
    var canvas_1 = document.getElementById("canvas_1");

    // 獲取在 canvas 上繪圖的 canvasRenderingContent2D 對象
    var ctx = canvas_1.getContext("2d");

    // 我們多去繪制幾個圓形,使用下 for 循環
    for(var i = 0; i < 10 ; i++){
        // 開始定義路徑
        ctx.beginPath();
        // 添加一段圓弧
        ctx.arc(i * 25,i * 25,(i + 1) * 8, 0, Math.PI * 2, true);
        // 關閉路徑
        ctx.closePath();
        // 設置填充顏色
        ctx.fillStyle = 'rgba(255,0,255,'+ (10 - i) * 0.1 + ')';
        // 填充當前路徑
        ctx.fill();
    }
</script>
</html>

最后實現效果如下:

Paste_Image.png

不知道小伙伴們是否看懂了上面的程序呢?

如果沒看懂也無所謂,咱們就來一起說一說上面內容中的難點。

首先說一下,Math.PI 實際上指代的就是 π,換而言之也就是 180°,那么我們上面使用的角度是 Math.PI * 2,也就是繪制了一個圓形。

之后再說一下 arc(float x,float y,float radius,float startAngle,float endAngle,boolean counterclockwise)這個方法。

里面一共有 6 個參數,這六個參數實際上對應的是:

- -
float x 指定圓弧的圓心的 X 坐標
float y 指定圓弧的圓心的 Y 坐標
float radius 指定圓弧的半徑
float startAngle 設置圓弧的開始角度
float endAngle 設置圓弧的結束角度
boolean counterclockwise 設置是否順時針旋轉

這樣不知道大家對我們繪制圓是否清楚明白了呢?

如果有任何疑問請及時留言回復呦。

1.2 繪制圓角矩形

我們之前已經學習過繪制圓形,也學習過繪制矩形,甚至我們也可以通過 lineJoin 去對我們的元素的圓角去進行修改。

但是,固定的東西我們不需要,我們真正需要的是可以自定義,可以根據我們想要的效果能夠隨意訂制的內容。

為了做到這個目的,我們還可以去使用 arcTo 來去繪制一段圓弧。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div>
        <h2>繪制圓形</h2>
        <canvas id="canvas_1" width="1000" height="500" style="box-shadow: 0px 0px 20px black;">
            當前瀏覽器不支持 canvas
        </canvas>
    </div>
</body>
<script type="text/javascript">
    /*
        該方法負責繪制圓角矩形
        x1 , y2 : 圓角矩形左上角的坐標
        width,height:控制圓角矩形的寬度和高度
        radius:控制圓角矩形的四個圓角的半徑
    */

    function creatRoundRect(ctx, x1, y1, width, height, radius){
        // 移動到左上角的開始點
        ctx.moveTo(x1 + radius, y1);
        // 添加一條連接開始點到右上角的線段
        ctx.lineTo(x1 + width - radius, y1);
        // 添加右上角的一段圓弧
        ctx.arcTo(x1 + width, y1, x1 + width, y1 + radius, radius);
        // 添加一條連接到右下角的線段
        ctx.lineTo(x1 + width, y1 + height - radius);
        // 添加右下角的一段圓弧
        ctx.arcTo(x1 + width, y1 + height, x1 + width - radius, y1 + height, radius);
        // 添加一條由右下角連接到左下角的線段
        ctx.lineTo(x1 + radius, y1 + height);
        // 添加左下的圓弧
        ctx.arcTo(x1, y1 + height, x1, y1 + height - radius,radius);
        // 添加一條由左下角連接到左上角的線段
        ctx.lineTo(x1, y1 + radius);
        // 添加一段圓弧
        ctx.arcTo(x1, y1, x1 + radius, y1, radius);
        ctx.closePath();
    }
    // 獲取 canvas 元素對應的 DOM 對象
    var canvas_1 = document.getElementById("canvas_1");

    // 獲取在 canvas 上繪圖的 canvasRenderingContent2D 對象
    var ctx = canvas_1.getContext("2d");

    ctx.lineWidth = 3;
    creatRoundRect(ctx, 30, 30, 200, 100, 20);
    ctx.stroke();
</script>
</html>

注意,我在這里分別繪制了四條線和四個弧度角,并且讓他們首尾相連,以此來達到繪制矩形框的作用。

其次就是專門去封裝了一個函數,用于繪制圓角矩形,回頭有需要的小伙伴可以直接自行粘貼呦。

Paste_Image.png

1.3 繪制多角形

不知道大家對之前繪制三角形是否還記得?

我們在繪制三角形的時候,主要是去使用 lineTo 和 moveTo 這兩個方法,可是我們在生活中遇到的圖形遠遠不止這么幾種圖形。

那么我們今天就來學習一下如何去繪制多角形。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div>
        <h2>繪制多角形</h2>
        <canvas id="canvas_1" width="1000" height="500" style="box-shadow: 0px 0px 20px black;">
            當前瀏覽器不支持 canvas
        </canvas>
    </div>
</body>
<script type="text/javascript">
    /*
        該方法用于繪制多角形
            n:該參數通常設置為奇數,控制繪制 N 角星
            dx、dy:控制 N 角星的位置
            size:控制 N 角星的大小
    */
    function creatStar(context, n, dx, dy, size){
        // 開始創建路徑
        context.beginPath();
        var dig = Math.PI / n * 4;
        context.moveTo(dx, y + dy);
        for(var i = 0; i <= n; i++){
            var x = Math.sin(i * dig);
            var y = Math.cos(i * dig);
            // 繪制從當前點連接到指定點的線條
            context.lineTo(x * size + dx, y * size + dy);
        }
        // 關閉路徑
        context.closePath();
    }

    // 獲取 canvas 元素對應的 DOM 對象
    var canvas_1 = document.getElementById("canvas_1");

    // 獲取在 canvas 上繪圖的 canvasRenderingContent2D 對象
    var ctx = canvas_1.getContext("2d");

    // 繪制三角星
    creatStar(ctx, 3, 60, 60, 50);
    ctx.fillStyle = '#f00';
    ctx.fill();
    // 繪制五角星
    creatStar(ctx, 5, 160, 60, 50);
    ctx.fillStyle = '#0f0';
    ctx.fill();
    // 繪制七角星
    creatStar(ctx, 7, 260, 60, 50);
    ctx.fillStyle = '#00f';
    ctx.fill();
    // 繪制九角星
    creatStar(ctx, 9, 360, 60, 50);
    ctx.fillStyle = '#f0f';
    ctx.fill();
</script>
</html>

可以看到我們又去封裝了一個方法,專門用于繪制多角星,當然我們也可以在這個基礎之上去繼續拓展,這些就需要看小伙伴們的發揮啦。

Paste_Image.png

1.4 繪制曲線

還記得我們在一開始的時候我們學習了五個方法,除了現在已經學習的繪制圓和繪制圓角矩形,是不是還有一些奇奇怪怪的方法?

那么我們現在就開始來學習這些方法。

首先先來學習一下,添加貝塞爾曲線。

- -
bezierCurveTo(float cpX1, float cpY1, float cpX2, float cpY2, float x, float y) 在當前路徑上添加一段貝塞爾曲線
quadraticCurveTo(float cpX, float cpY,float x,float y) 向 canvas 當前路徑添加一段二次貝塞爾曲線

首先來看看第一個方法,第一個方法中實際上有四個點需要注意。

Paste_Image.png

他們分別是

  • 左下角的開始點
  • 粉紅色的第一個控制點(錨點)
  • 藏青色的第二個控制點(錨點)
  • 右上角的結束點

而方法中 cpX1 和 cpY1 則是控制第一個控制點的坐標,

后面的 cpX2 和 cpY2 則是控制第二個控制點的坐標。

而二次貝塞爾曲線又是怎么回事呢?

Paste_Image.png

和正常貝塞爾不同,二次曲線只需要三個點:

  • 左下角的開始點
  • 藏青色的控制點
  • 右上角的結束點

方法中的 cpX 和 cpY 則是去設置控制點的坐標。

那么我們來一起試一試,該如何去繪制一個個花朵。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div>
        <h2>繪制花朵</h2>
        <canvas id="canvas_1" width="1000" height="500" style="box-shadow: 0px 0px 20px black;">
            當前瀏覽器不支持 canvas
        </canvas>
    </div>
</body>
<script type="text/javascript">
    /*
        該方法負責繪制花朵
            n:該參數控制花朵的花瓣數
            dx,dy:控制花朵的位置
            size:控制花朵的大小
            length:控制花瓣的長度
    */
    function creatFlower(context, n, dx, dy, size, length){
        // 開始創建路徑
        context.beginPath();
        context.moveTo(dx, dy + size);
        var dig = 2 * Math.PI / n;
        for(var i = 1; i < n + 1; i++){
            // 計算控制點的坐標
            var ctrlX = Math.sin((i - 0.5) * dig) * length + dx;
            var ctrlY = Math.cos((i - 0.5) * dig) * length + dy;
            // 計算結束點的坐標
            var x = Math.sin(i * dig) * size + dx;
            var y = Math.cos(i * dig) * size + dy;
            // 繪制二次曲線
            context.quadraticCurveTo(ctrlX, ctrlY, x, y);
        }
        context.closePath();
    }
    // 獲取 canvas 元素對應的 DOM 對象
    var canvas_1 = document.getElementById("canvas_1");
    // 獲取在 canvas 上繪圖的 canvasRenderingContent2D 對象
    var ctx = canvas_1.getContext("2d");
    // 繪制五瓣的花朵
    creatFlower(ctx, 5, 70, 100, 30, 80);
    ctx.fillStyle = "#f00";
    ctx.fill();
    // 繪制六瓣的花朵
    creatFlower(ctx, 6, 220, 100, 30, 80);
    ctx.fillStyle = "#ff0";
    ctx.fill();
    // 繪制七瓣的花朵
    creatFlower(ctx, 7, 370, 100, 30, 80);
    ctx.fillStyle = "#f0f";
    ctx.fill();
</script>
</html>
Paste_Image.png

1.5 繪制位圖

一直到現在我們講了如何去繪制線,三角形,多角星,矩形,圓,花朵,圓角矩形等各種圖形。

但是除了這些基礎圖形之外,我們還可以去繪制“位圖”,讓一張圖片繪制在我們的畫布之上。

那我們怎么來做呢?

我們既然想將我們的圖片載入到我們的畫布中,怎么做呢?我們先來差混構建一個 Image 對象。

var image = new Image();
image.src = "lipeng.png";

需要注意兩點,

  • 我們的程序只是創建,加載圖片,所以調用 image 時無需傳入寬度和高度,這樣創建的 image 將會與 src 屬性指定的圖片保持相同的寬度和高度。
  • src 加載圖片是進行異步加載,如果圖片數據太大,或者直接來自于網絡,當我們網速較慢的時候,會發現我們的圖片繪制會非常慢,導致影響用戶使用。我們可以使用 onload 去保證我們一定是在圖片加載完成后再繪制。
var image = new Image();
image.src = "lipeng.png";
image.onload =  function(){
  //繪制圖片
}

學習了如何去加載圖片,我們就可以向我們的畫布中添加圖片了么?

沒有方法你怎么去添加圖片呀,魂淡。

我們還要學習添加圖片的方法,這里跟大家說三種方法。

- -
drawImage(Image image, float x, float y) 把 image 繪制在 x, y 處。該方法不會對圖片做任何縮放處理,繪制處理的圖片保持原來的大小
drawImage(Image image, float x, float y, float width, float height) 把 image 繪制在 x, y 處。該方法會對圖片進行縮放,繪制出來的寬度為 width,高度為 height。
drawImage(Image image, integer sx, integer sy, integer sw, integer sh, float dx, float dy,float dw, float dh) 該方法將會從 image 上“挖出”一塊繪制到畫布上。其中 sx, sy 兩個參數控制從原圖片上的哪一個位置開始挖去, sw, sh 兩個參數控制從原圖片挖球的寬度和高度;dx, dy 兩個參數控制把挖取的圖片繪制到畫布上的哪個位置,而 dw, dh 則控制對繪制圖片進行縮放,繪制出來的寬度是 dw, 高度 dh

我們知道了方法,那就來一起學習下,該如何用代碼來實現吧。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div>
        <h2>繪制位圖</h2>
        <canvas id="canvas_1" width="1000" height="500" style="box-shadow: 0px 0px 20px black;">
            當前瀏覽器不支持 canvas
        </canvas>
    </div>
</body>
<script type="text/javascript">
    // 獲取 canvas 元素對應的 DOM 對象
    var canvas_1 = document.getElementById("canvas_1");

    // 獲取在 canvas 上繪圖的 canvasRenderingContent2D 對象
    var ctx = canvas_1.getContext("2d");

    // 創建 image 對象
    var image = new Image();
    // 創建 image 對象裝載圖片
    image.src = "lipeng.png";
    // 當圖片加載完成后觸發該函數
    image.onload = function(){
        // 保持原大小繪制圖片
        ctx.drawImage(image, 20, 10);
        // 繪制圖片的時候進行縮放
        ctx.drawImage(image, 600, 10, 76, 110);
        // 從原圖中挖去一塊,放大三倍后繪制在 canvas 上
        var sd = 50;
        var sh = 50;
        /*
        參數說明
            Image image, integer sx, integer sy, integer sw, integer sh, float dx, float dy,float dw, float dh

            sx, sy 兩個參數控制從原圖片上的哪一個位置開始挖去,
            sw, sh 兩個參數控制從原圖片挖球的寬度和高度;
            dx, dy 兩個參數控制把挖取的圖片繪制到畫布上的哪個位置,而
            dw, dh 則控制對繪制圖片進行縮放,繪制出來的寬度是 dw, 高度 dh
        */
        ctx.drawImage(image, 230, 220,sd, sh, 765, 10, sd * 3, sh * 3);
    }
</script>
</html>

結果如下:

Paste_Image.png

怎么樣,是不是覺得瞬間高大上了呢?趕快學起來啦。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 一:canvas簡介 1.1什么是canvas? ①:canvas是HTML5提供的一種新標簽 ②:HTML5 ...
    GreenHand1閱讀 4,718評論 2 32
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,155評論 25 708
  • 前言 自定義View是Android開發者必須了解的基礎;而Canvas類的使用在自定義View繪制中發揮著非常重...
    Carson帶你學安卓閱讀 28,596評論 7 219
  • (簡書-打賞)美篇打賞入袋里,昨晚沒眠看簡書。點點看看亂翻看,看見打賞二百六。默默勤耕不理事,點點耕耘樹藝成。人生...
    甘朝武閱讀 475評論 0 0
  • 開一個“果書”:有健康的果蔬汁;營養的簡裝書;一個信箱可以收取你的煩惱,它們也會得到用心的反饋;男店主熱愛音樂,每...
    小小小小小猴子閱讀 199評論 0 0