Day08 - HTML5 Canvas 實現彩虹畫筆繪畫板指南

Day08 - HTML5 Canvas 實現彩虹畫筆繪畫板指南

做者:©liyuechun
簡介:JavaScript30Wes Bos 推出的一個 30 天挑戰。項目免費提供了 30 個視頻教程、30 個挑戰的起始文檔和 30 個挑戰解決方案源代碼。目的是幫助人們用純 JavaScript 來寫東西,不借助框架和庫,也不使用編譯器和引用。如今你看到的是這系列指南的第 8 篇。完整中文版指南及視頻教程在 從零到壹全棧部落javascript

項目效果

用 HTML5 中的 Canvas 的路徑繪製實現一個繪畫板,可供鼠標畫畫,顏色呈彩虹色漸變,畫筆大小一樣呈漸變效果。這部分不涉及 CSS 內容,所有由 JS 來實現。css

涉及特性

Canvas:html

  • 模板骨架java

  • 基本屬性git

    • getContext()github

    • strokeStyle編程

    • fillStylecanvas

    • fillRect瀏覽器

    • lineCap微信

    • lineJoin

  • 路徑繪製

    • beginPath()

    • lineTo()

    • moveTo()

    鼠標事件處理:

  • mousemove

  • mousedown

  • mouseup

  • mouseout

過程指南

  1. 獲取 HTML 中的 <canvas> 元素,並設定寬度和高度

  2. .getContext('2d') 獲取上下文,下面以 ctx 表示

  3. 設定 ctx 基本屬性

    • 描邊和線條顏色

    • 線條寬度

    • 線條末端形狀

  4. 繪畫效果

    1. 設定一個用於標記繪畫狀態的變量

    2. 鼠標事件監聽,不一樣類型的事件將標記變量設爲不一樣值

    3. 編寫發生繪製時觸發的函數,設定繪製路徑起點、終點

  5. 線條彩虹漸變效果(運用 hsl 的 h 值的變化,累加)

  6. 線條粗細漸變效果(設定一個範圍,當超出這個範圍時,線條粗細進行逆向改變

Canvas相關知識

Canvas_API

HelloWorld簡單介紹

1、 模板骨架

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>HTML5 Canvas 實現彩虹畫筆繪畫板</title>
  <script type="text/javascript">
    function draw() {
      var canvas = document.getElementById('tutorial');
      if (canvas.getContext) {
        var ctx = canvas.getContext('2d');
      }
    }
  </script>
  <style type="text/css">
    canvas {
      border: 1px solid black;
    }
  </style>
</head>

<body>
  <canvas id="tutorial" width="150" height="150"></canvas>
</body>

</html>
  • canvas> 元素

<canvas id="tutorial" width="150" height="150"></canvas>

canvas 看起來和 img 元素很相像,惟一的不一樣就是它並無 srcalt 屬性。實際上,canvas 標籤只有兩個屬性——widthheight。這些都是可選的,而且一樣利用 DOM properties 來設置。當沒有設置寬度和高度的時候,canvas會初始化寬度爲300像素和高度爲150像素。該元素能夠使用CSS來定義大小,但在繪製時圖像會伸縮以適應它的框架尺寸:若是CSS的尺寸與初始畫布的比例不一致,它會出現扭曲。

  • 渲染上下文(The rendering context)

var canvas = document.getElementById('tutorial');
var ctx = canvas.getContext('2d');

canvas元素創造了一個固定大小的畫布,它公開了一個或多個渲染上下文,其能夠用來繪製和處理要展現的內容。

canvas起初是空白的。爲了展現,首先腳本須要找到渲染上下文,而後在它的上面繪製。canvas元素有一個叫作 getContext() 的方法,這個方法是用來得到渲染上下文和它的繪畫功能。getContext()只有一個參數,上下文的格式。對於2D圖像而言,基本教程,你能夠使用CanvasRenderingContext2D

  • 檢查支持性

替換內容是用於在不支持 canvas 標籤的瀏覽器中展現的。經過簡單的測試getContext()方法的存在,腳本能夠檢查編程支持性。

var canvas = document.getElementById('tutorial');

if (canvas.getContext){
    //支持
  var ctx = canvas.getContext('2d');
  // drawing code here
} else {
   //不支持
  // canvas-unsupported code here
}

2、一個簡單例子

一開始,讓咱們來看個簡單的例子,咱們繪製了兩個有趣的長方形,其中的一個有着alpha透明度。咱們將在接下來的例子裏深刻探索一下這是如何工做的。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>HTML5 Canvas 實現彩虹畫筆繪畫板</title>
  <script type="text/javascript">
    function draw() {
      var canvas = document.getElementById('tutorial');
      if (canvas.getContext) {
        var ctx = canvas.getContext('2d');
        ctx.fillStyle = "rgb(200,0,0)";
        ctx.fillRect (10, 10, 55, 50);

        ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
        ctx.fillRect (30, 30, 55, 50);
      }
    }
  </script>
  <style type="text/css">
    canvas {
      border: 1px solid black;
    }
  </style>
</head>

<body onload="draw();">
  <canvas id="tutorial" width="300" height="300"></canvas>
</body>

</html>

效果圖:

項目源碼分析

源碼

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>HTML5 Canvas</title>
  <style>
    html,
    body {
      margin: 0;
      overflow: hidden;
    }

    canvas {
      overflow: hidden;
    }
  </style>
</head>

<body>
  <canvas id="draw" width="800" height="800" style="overflow:auto;"></canvas>
  <script>

    // 1.獲取canvas節點
    const canvas = document.querySelector('#draw');

    if (canvas.getContext) {
      //支持
      var ctx = canvas.getContext('2d');
      // drawing code here
    } else {
      //不支持
      // canvas-unsupported code here
      console.log("canvas-unsupported code here");
    }

    
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

    let isDrawing = false;
    let lastX = 0;
    let lastY = 0;

    ctx.lineWidth = 90;
    ctx.lineCap = "round";
    ctx.lineJoin = "round";
    ctx.strokeStyle = "#f00";
    ctx.fillStyle = "#f00";

    let hue = 0;
    let direction = true;
    let x = 0;
    let y = 0;

    function draw(e) {
      if (!isDrawing) return;


      x = e.offsetX;
      y = e.offsetY;


      //        彩虹效
      ctx.strokeStyle = `hsl(${ hue }, 90%, 50%)`;
      if (hue >= 360) hue = 0;
      hue++;


      //        控制筆觸大小
      if (ctx.lineWidth > 120 || ctx.lineWidth < 10) {
        direction = !direction;
      }
      if (direction) {
        ctx.lineWidth++;
      } else {
        ctx.lineWidth--;
      }

      //        控制繪製路徑
      ctx.beginPath();

      ctx.moveTo(lastX, lastY);
      ctx.lineTo(x, y);
      ctx.stroke();

      [lastX, lastY] = [x, y];

    }
    canvas.addEventListener('mousedown', (e) => {
      isDrawing = true;
      [lastX, lastY] = [e.offsetX, e.offsetY];
    });

    canvas.addEventListener('mousemove', draw);
    canvas.addEventListener('mouseup', () => isDrawing = false);
    canvas.addEventListener('mouseout', () => isDrawing = false);
  </script>

</body>

</html>

源碼分析

Canvas

canvas寬高設置

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

屬性

  • lineCap:筆觸的形狀,有 round | butt | square 圓、平、方三種。

  • lineJoin:線條相交的樣式,有 round | bevel | miter 圓交、斜交、斜接三種。

  • lineWidth:線條的寬度

  • strokeStyle:線條描邊的顏色

  • fillStyle:填充的顏色

方法

  • beginPath():新建一條路徑

  • stroke():繪製輪廓

  • moveTo():(這次)繪製操做的起點

  • lineTo():路徑的終點

彩虹漸變顏色——HSL

在這個挑戰中,涉及到改變線條的顏色,如何實現彩虹的漸變效果?咱們須要利用 HSL 色彩模式,首先能夠去這個網站 http://mothereffinghsl.com 感覺一下 HSL 不一樣色彩值對應的效果。

  • H(hue) 表明色調,取值爲 0~360,專業術語叫色相

  • S 是飽和度,能夠理解爲摻雜進去的灰度值,取值爲 0~1

  • L 則是亮度,取值也是 0~1,或者百分比。

    這之中 H 值從 0 到 360 的變化表明了色相的角度的值域變化,利用這一點就能夠實現繪製時線條顏色的漸變了,只須要在它的值超過 360 時恢復到 0 從新累加便可。

let hue = 0;

ctx.strokeStyle = `hsl(${ hue }, 100%, 50%)`;    
if(hue >= 360) hue = 0;
hue++;

除此以外,若是想實現黑白水墨的顏色,能夠將顏色設置爲黑色,經過透明度的改變來實現深淺不一的顏色。

控制筆觸大小

//        控制筆觸大小
 if (ctx.lineWidth > 120 || ctx.lineWidth < 10) {
   direction = !direction;
 }
 if (direction) {
   ctx.lineWidth++;
 } else {
   ctx.lineWidth--;
 }

上面的代碼中,根據線條的寬度的變化來控制direction的值,根據direction的值來控制線寬是增長仍是減小。

控制線條路徑

//        控制繪製路徑
 ctx.beginPath();

 ctx.moveTo(lastX, lastY);
 ctx.lineTo(x, y);
 ctx.stroke();

// 座標重置
 [lastX, lastY] = [x, y];

事件監聽代碼邏輯分析

canvas.addEventListener('mousedown', (e) => {
<!--開始繪圖-->
 isDrawing = true;
 <!--繪圖起始座標初始化-->
 [lastX, lastY] = [e.offsetX, e.offsetY];
});

<!--鼠標移動時,調用draw方法-->
canvas.addEventListener('mousemove', draw);
<!--鼠標擡起時,將isDrawing置爲false-->
canvas.addEventListener('mouseup', () => isDrawing = false);
<!--當鼠標不在可繪圖區域範圍內時,將isDrawing置爲fals-->
canvas.addEventListener('mouseout', () => isDrawing = false);

源碼下載

Github Source Code

社羣品牌:從零到壹全棧部落

定位:尋找共好,共同窗習,持續輸出全棧技術社羣

業界榮譽:IT界的邏輯思惟

文化:輸出是最好的學習方式

官方公衆號:全棧部落

社羣發起人:春哥(從零到壹創始人,交流微信:liyc1215)

技術交流社區:全棧部落BBS

全棧部落完整系列教程:全棧部落完整電子書學習筆記

關注全棧部落官方公衆號,每晚十點接收系列原創技術推送
相關文章
相關標籤/搜索