2010/08/25 カテゴリ : HTML5  canvas  Tech  JavaScript 

【HTML5】Canvasでお絵かきしてみた(前編)

こんにちは、橋本です。

今回はHTML5シリーズ第二弾ということで、canvasを使ってお絵かきしてみました。
今回は前編で、基本的な機能について触れてみたいと思います。

さっそくサンプルコードを以下に。

canvas_sample.html
  1. <html lang="ja">
  2. <head>
  3.   <meta charset="UTF-8">
  4.     <script src="js/canvas.js" type="text/javascript"></script>
  5.     <link media="all" rel="stylesheet" href="css/main.css" type="text/css" />
  6.     <title>canvas test</title>
  7. </head>
  8. <body>
  9.     <div id="container">
  10.         <div id="leftContainer" class="clearfix">
  11.             <canvas id="layer0" class="canvas" style="position: absolute; top: 0; left: 0; border: 10px solid #dddddd;" width="900px" height="600px"></canvas>
  12.         </div>
  13.         <div id="rightContainer">
  14.             <div id="controler">
  15.                 <section id="color">
  16.                     <ul>
  17.                         <li>
  18.                             <label for="red">R:</label>
  19.                             <input id="red" class="colorBar" type="range" min="0" max="255">
  20.                         </li>
  21.                         <li>
  22.                             <label for="green">G:</label>
  23.                             <input id="green" class="colorBar" type="range" min="0" max="255">
  24.                         </li>
  25.                         <li>
  26.                             <label for="blue">B:</label>
  27.                             <input id="blue" class="colorBar" type="range" min="0" max="255">
  28.                         </li>
  29.                         <li>
  30.                             <label for="alpha">A:</label>
  31.                             <input id="alpha" class="colorBar" type="range" min="0" max="100">
  32.                         </li>
  33.                         <li>
  34.                             <canvas id="colorSample" height="30px" width="30px"></canvas>
  35.                             <input id="colorText" type="text" value="" readonly="true">
  36.                         </li>
  37.                     </ul>
  38.                 </section>
  39.                 <section id="line">
  40.                     <ul>
  41.                         <li>
  42.                             <label for="lineWidthRange">line width:</label>
  43.                             <input id="lineWidthRange" type="range" min="0" max="50">
  44.                         </li>
  45.                         <li>
  46.                             <canvas id="lineSample" width="50" height="50"></canvas>
  47.                         </li>
  48.                     </ul>
  49.                 </section>
  50.                 <section id="other">
  51.                     <ul>
  52.                         <li>
  53.                             <label for="erase">erase mode:</label>
  54.                             <input id="erase" type="checkbox" />
  55.                         </li>
  56.                     </ul>
  57.                 </section>
  58.             </div>
  59.         </div>
  60.     </div>
  61. </body>
  62. </html>

canvas.js
  1. (function(){
  2.  
  3.   var canvas,context = null;
  4.   var beforeX, beforeY = null;
  5.   var isDrawing =  false;
  6.   var selectedColor;
  7.   var colorVars;
  8.   var colorText;
  9.   var colorSample;
  10.   var erase;
  11.   var restore;
  12.   var lineWidthRange;
  13.   var lineWidth;
  14.   var lineSample;
  15.   var isErase;
  16.  
  17.   window.addEventListener("load", function (event){
  18.     canvas = document.getElementById("layer0");
  19.     context = canvas.getContext("2d");
  20.  
  21.     erase = document.getElementById("erase");
  22.     restore = document.getElementById("restore");
  23.     lineWidthRange = document.getElementById("lineWidthRange");
  24.  
  25.     // イベントリスナーの設定
  26.     canvas.addEventListener("mousemove", canvas_mouseMoveHandler, false);
  27.     canvas.addEventListener("mouseup", canvas_mouseUpHandler, false);
  28.     canvas.addEventListener("mousedown", canvas_mouseDownHandler, false);
  29.     canvas.addEventListener("mouseout", canvas_mouseOutHandler, false);
  30.  
  31.     erase.addEventListener("click", erase_clickHandler, false);
  32.     lineWidthRange.addEventListener("change", lineWidthRange_changeHandler, false);
  33.     
  34.  
  35.     //controlerの設定
  36.     colorBars = document.getElementsByClassName("colorBar");
  37.  
  38.     var obj = {};
  39.  
  40.     length = colorBars.length;
  41.     for (var i = 0; i < length; i++)
  42.     {
  43.         var bar = colorBars[i];
  44.         bar.value = bar.id == "alpha" ? 100 : 0;
  45.  
  46.         bar.addEventListener("change", colorBar_changeHandler, false);
  47.  
  48.         obj[bar.id] = bar.value;
  49.     }
  50.  
  51.     colorSample = document.getElementById("colorSample");
  52.     colorText = document.getElementById("colorText");
  53.  
  54.     var colorStr = convertColorObjToStr(obj);
  55.  
  56.     setColorText(colorStr);
  57.     setSelectedColor(colorStr);
  58.  
  59.     setColorSample();
  60.  
  61.     lineWidthRange.value = 10;
  62.     lineWidth = 10;
  63.     lineSample = document.getElementById("lineSample");
  64.  
  65.     setLineSample();
  66.  
  67.   }, false);
  68.  
  69.   function convertColorObjToStr(obj)
  70.   {
  71.       return obj["red"] + ", " + obj["green"] + ", " + obj["blue"] + ", " + (obj["alpha"] / 100);
  72.   }
  73.  
  74.   function setColorSample()
  75.   {
  76.       var context = colorSample.getContext("2d");
  77.  
  78.       context.beginPath();
  79.       context.strokeStyle = selectedColor;
  80.       context.fillStyle = selectedColor;
  81.       context.fillRect(0, 0, colorSample.width, colorSample.height);
  82.   }
  83.  
  84.   function setLineSample()
  85.   {
  86.       var context = lineSample.getContext("2d");
  87.       // 今の状態をリセット
  88.       context.clearRect(0, 0, lineSample.width, lineSample.height);
  89.  
  90.       context.beginPath();
  91.       context.arc(lineSample.width / 2, lineSample.height / 2, lineWidth / 2, 0, Math.PI*2, false);
  92.  
  93.       if (isErase)
  94.       {
  95.           context.strokeStyle = "rgba(0, 0, 0, 1)";
  96.           context.stroke();
  97.       }
  98.       else
  99.       {
  100.           context.strokeStyle = selectedColor;
  101.           context.fillStyle = selectedColor;
  102.           context.fill();
  103.       }
  104.   }
  105.  
  106.   function setColorText(colorStr)
  107.   {
  108.       colorText.value = colorStr;
  109.   }
  110.  
  111.   function setSelectedColor(colorStr)
  112.   {
  113.       selectedColor = "rgba(" + colorStr + ")";
  114.   }
  115.  
  116.   function colorBar_changeHandler(event)
  117.   {
  118.       var obj = {};
  119.  
  120.       length = colorBars.length;
  121.       for (var i = 0; i < length; i++)
  122.       {
  123.           var bar = colorBars[i];
  124.           obj[bar.id] = bar.value;
  125.       };
  126.  
  127.       var colorStr = convertColorObjToStr(obj);
  128.  
  129.       setColorText(colorStr);
  130.       setSelectedColor(colorStr);
  131.  
  132.       setColorSample();
  133.       setLineSample();
  134.   }
  135.  
  136.   function canvas_mouseOutHandler(event)
  137.   {
  138.       isDrawing = false;
  139.   }
  140.  
  141.   function canvas_mouseDownHandler(event)
  142.   {
  143.       isDrawing = true;
  144.       beforeX = event.clientX - 10;
  145.       beforeY = event.clientY - 10;
  146.   }
  147.  
  148.   function canvas_mouseUpHandler(event)
  149.   {
  150.       isDrawing = false;
  151.   }
  152.  
  153.   function canvas_mouseMoveHandler(event)
  154.   {
  155.       if (!isDrawing)
  156.       {
  157.           return;
  158.       }
  159.  
  160.       isErase ? eraseLine(event) : drawLine(event);
  161.   }
  162.  
  163.   function drawLine(event)
  164.   {
  165.       var fixedX = event.clientX - 10;
  166.       var fixedY = event.clientY - 10;
  167.       
  168.       context.beginPath();
  169.  
  170.       context.strokeStyle = selectedColor;
  171.       context.lineWidth = lineWidth;
  172.       context.lineCap = 'round';
  173.       context.lineJoin = 'round';
  174.       context.moveTo(beforeX, beforeY);
  175.       context.lineTo(fixedX, fixedY);
  176.       context.stroke();
  177.  
  178.       context.closePath();
  179.  
  180.       beforeX = fixedX;
  181.       beforeY = fixedY;
  182.   }
  183.  
  184.   function eraseLine(event)
  185.   {
  186.       var x = event.clientX - 10 - lineWidth / 2;
  187.       var y = event.clientY - 10 - lineWidth / 2;
  188.  
  189.       context.clearRect(x, y, lineWidth, lineWidth);
  190.   }
  191.  
  192.   function erase_clickHandler(event)
  193.   {
  194.       isErase = event.target.value;
  195.       setLineSample();
  196.   }
  197.  
  198.   function lineWidthRange_changeHandler(event)
  199.   {
  200.       lineWidth = event.target.value;
  201.       setLineSample();
  202.   }
  203.   
  204.  
  205. })();

*cssは略

JSのコードが結構汚いんですが、サンプルってことで華麗にスルーしていただけると幸いです。(次回までに綺麗にしておきます;)

実際のサンプルはこちら


まず、canvasで画像を描画する際には、対象のcanvasのcontextを取得します。
  1.     canvas = document.getElementById("layer0");
  2.     context = canvas.getContext("2d");
contextに対して処理を行うことで、画像を描画することが出来ます。

次に基本的な線を引く処理。
線を引くためには、以下の手順を踏みます。
  1. // 1. 線を描きますよーと宣言
  2. context.beginPath();
  3.  
  4. // 2. 線の設定(しなくてもOK)
  5. context.strokeStyle = selectedColor; // 線の色
  6. context.lineWidth = lineWidth; // 線の太さ
  7. context.lineCap = 'round'; // 線の始点、終点の形
  8. context.lineJoin = 'round'; // 線のつなぎ目の形
  9.  
  10. // 3. 線の始点を設定
  11. context.moveTo(beforeX, beforeY);
  12.  
  13. // 4. 線の終点を設定
  14. context.lineTo(fixedX, fixedY);
  15.  
  16. // 5. 線を描く
  17. context.stroke();
  18.  
  19. // 6. 線が書き終わりましたよーという宣言
  20. context.closePath();

線の各種設定については、以下のページに詳しく載ってるので参照してください。
HTML5.jp-Canvasリファレンス

今回のサンプルでは、連続した線を引くために、線を引き終わった座標を、beforeX, beforeYに格納し、次の線を描き始めるときの始点として指定しています。

次に四角形を描く処理。
四角形を描くためには、以下の手順を踏みます。
  1. // 1.線を描きますよーの宣言
  2. context.beginPath();
  3.  
  4. // 2. 設定
  5. context.strokeStyle = selectedColor; // 線の色
  6. context.fillStyle = selectedColor; // 塗りつぶしの色
  7.  
  8. // 3. 四角形を描く
  9. context.fillRect(0, 0, colorSample.width, colorSample.height);

上記サンプルのfillRectは、塗りつぶした四角形を描くメソッドです。
引数は、書き始めるx座標、書き始めるy座標、四角形の幅、四角形の高さとなっています。
座標は、左上が(0, 0)です。これは、canvas全体共通です。

ちなみに、枠だけの四角形を描きたいときは、strokeRect()、四角形を消したいときは、clearRect()メソッドを使います。今回のサンプルでは、消しゴムを実装するために、clearRect()メソッドを使っています。

次は円を描く処理です。
円を描くためには以下の手順。
  1. // 1. 例のやつ
  2. context.beginPath();
  3.  
  4. // 2. 円の形を指定
  5. context.arc(lineSample.width / 2, lineSample.height / 2, lineWidth / 2, 0, Math.PI*2, false);
  6.  
  7. // 3. オプションを指定
  8. context.strokeStyle = selectedColor;
  9. context.fillStyle = selectedColor;
  10.  
  11. // 4. 描く
  12. context.fill();

まず、arc()メソッドを使って円の設定をします。
引数は、円の中心のx座標、円の中心のy座標、円の半径、円を書き始める角度、円を書き終える角度、円を描く向きとなっています。最後の引数の円を描く向きは、trueを指定すると、反時計回り、falseを指定すると、時計回りになります。

今回は普通の円なので、最後の指定はあまり意味がないのですが、一部が欠けている円を描きたい時には、向きが重要になってくると思います。

ちなみに、枠だけの円を描きたいときは、最後のfill()をstroke()に変更すればOKです。


今回はとりあえず、ここまで。

次回後編では、グラデーション、画像の取り込みなどについて触れていきたいと思います。

コメントフォーム

認証
captcha_key
 
 

トラックバックURI

最近の記事

アシアルPHP書籍情報