第 361 篇 · 第 14 卷 前端,沒有極限 2026 年 6 月 9 日 · 台北
ls -lt ./posts --since=2013 REC · node 361 · uplink

canvas

試試看Canvas (3),Canvas 小畫家

2014 年 12 月 09 日 · 6 分鐘閱讀 · By Wang Casper

這篇也是前一個Blog的文章,最近在整理就一起拿出來。

翻翻一年之前做的,才發現原來有很多很酷的東西,還好有寫成簡易的文章,讓現在再重新看可以很快瞭解,這篇是介紹用Canvas做小畫家,並且還可以下載下來的功能,有分為好幾段,這邊全部合併成一篇。

參考:http://codepen.io/hossman/pen/AyaFl

範例

在開始介紹之前,先了解這個範例,這樣會更瞭解本篇所介紹的內容,Canvas範例的功能:

  1. 繪製線段
  2. 存檔
  3. 調整RGB色彩

所以可以在這上面隨意畫個幾筆,在調整色彩,最後在下載看看,這個功能簡簡單單,但是做出來挺有成就感的。

R
G
B
R G B
Sorry, your browser doesn't support the <canvas> element.

請先在上面隨便畫兩筆

Save Canvas

HTML

在看JS之前,先稍微看一下這個html,這HTML也和上面一樣,分為三個部分。

<div class="demo">
<!-- 調整色彩 -->
  <div class="color">
  R<input id="red" type="range" name="points" min="0" max="255" value="0"><br>
  G<input id="green" type="range" name="points" min="0" max="255" value="0"><br>
  B<input id="blue" type="range" name="points" min="0" max="255" value="0">
  </div>
  <div class="value">
    R<input id="vred" type="text" value="0">
    G<input id="vgreen" type="text" value="0">
    B<input id="vblue" type="text" value="0">
  </div>
<!-- 調整色彩end -->
<!-- Canvas -->
  <canvas id="canvas" width="400" height="400">
    Sorry, your browser doesn't support the &lt;canvas&gt; element.
  </canvas>
<!-- Canvas end -->
<!-- 下載 -->
  <a id="save" href="#" download="aShareaDay.png" class="color-btn-green">Save Canvas</a>
<!-- 下載end -->
</div>

繪製線段

這篇是前幾篇的綜合,還有參考http://codepen.io/hossman/pen/AyaFl所製作出來的。

這一段的重點在於,取得滑鼠的座標getMousePos(canvas, evt),先取得滑鼠在畫布上的座標,在每次滑鼠移動時,都會繪製在畫布上,然後再放開滑鼠時,離開偵聽的事件。

下載

Html5 的 a 有新的屬性download,可以將此標籤預設為下載的功能,並且預設檔名,另外在canvas可以利用toDataURL()把canvas轉成data:image。。

<!-- html5 新增download,可以用來預設下載檔名 -->
<a id="save" href="#" download="dl.png" >Save Canvas</a>

如果把產生出來的src貼在網址列,也能產生完整的圖片。

data:image參考:http://rritw.com/a/bianchengyuyan/C__/20131018/434112.html

調整色彩

接下來在抓取那三個scroll bar的rgb值,將它直接寫入到ctx.strokeStylestrokeStyle是Canvas上的筆畫樣式,這樣就大功告成了。

$('.color input').change(function(){
    r = $('#red').val();
    g = $('#green').val();
    b = $('#blue').val();
    changeColor(r,g,b);
    //取出input中的數值
  });

function changeColor(r,g,b){
  ctx.strokeStyle = "rgb("+r+","+g+","+b+")"  
  //將數值寫入到 strokeStyle內即可
};

完整程式碼

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

$('.color input').change(function(){
  r = $('#red').val();
  g = $('#green').val();
  b = $('#blue').val();
  changeColor(r,g,b);
  //取出input中的數值
});

function changeColor(r,g,b){
  colors = {
    red : r,
    green : g,
    blue : b
  }
  $.each(colors, function(_color, _value) {
    $('#v'+_color).val(_value);
  });
  ctx.strokeStyle = "rgb("+r+","+g+","+b+")" ;
  //將顏色的值寫到ctx.strokeStyle即可
};

var x = 0;
var y = 0;

function getMousePos(canvas, evt) {
  var rect = canvas.getBoundingClientRect();
  //getBoundingClientRect 取得物件完整座標資訊,包含寬高等
  return {
    x: evt.clientX - rect.left,
    y: evt.clientY - rect.top
  };   
  //這個function將會傳回滑鼠在 _canvas上的座標
};

function mouseMove(evt) {
  var mousePos = getMousePos(_canvas, evt);
  //透過getMousePos function 去取得滑鼠座標
  //mousePos 是一個物件,包含x和y的值
  ctx.lineTo(mousePos.x, mousePos.y);
  //利用取回的值畫線
  ctx.stroke();
  //畫!
};

canvas.addEventListener('mousedown', function(evt) {
  var mousePos = getMousePos(_canvas, evt);
  //從按下去就會執行第一次的座標取得
  evt.preventDefault();
  ctx.beginPath();
  //建立path物件
  ctx.moveTo(mousePos.x, mousePos.y);  
  //每次的點用moveTo去區別開,如果用lineTo會連在一起  
  canvas.addEventListener('mousemove', mouseMove, false);
  //mousemove的偵聽也在按下去的同時開啟
});

canvas.addEventListener('mouseup', function() {
  canvas.removeEventListener('mousemove', mouseMove, false);
}, false);
//如果滑鼠放開,將會停止mouseup的偵聽

$('#save').on('click', function(){
  var _url = _canvas.toDataURL();
  //利用toDataURL() 把canvas轉成data:image
  this.href = _url;
  //再把href載入上面的Data:image
});

在畫個小新,滑鼠挺有挑戰性的…。

雖然是一些舊的文章,但現在回頭過來看,還是有許多有趣的點,甚至可以用這些概念,配合現在會的技術,發展出更有趣的玩具。