■補講 Canvasを使って塗り絵をするには? 第7章ではCanvasを使ったサンプルを作成しました。漢字の練習だと堅苦しいなあ、と思った人がいるかもしれません。お絵かきソフトとかにした方がいいんじゃないの?という人もいるかもしれません。ということで、ここでは本書で説明している漢字練習のプログラム(レッスン27のプログラム)を再利用して、塗り絵ができるWebアプリを作成してみましょう。 ------------------------------------------------------------------------------------------------ ■線画に着色 塗り絵なら簡単だろうと思う人がいるかもしれません。もし、全く塗り絵アプリを作ったことがない人だと、とりあえずCanvasに線画を描画して、そこに塗ればよさそうだと考えるでしょう。ただ、実際にやってみると大きな問題がある事がわかります。そう、塗ると線が消えてしまうのです。線が消えてしまうと、どこを塗っていいのかがわかりません。 それでは、どうすればよいのでしょうか? HTML5+Canvasであれば2枚のCanvasを重ねておき、前面には線画、背面に色を塗るというようにすると非常に簡単に塗り絵が実現できます。 ------------------------------------------------------------------------------------------------ ■Canvasを2枚重ねる まず、Canvasを2枚重ねます。HTMLでは以下のように2つcanvs要素を書いておきます。myCanvasが線画、myCanvas2が着色するCanvasです。 次に2枚のCanvas重ねるのでCSSで以下のように設定します。 canvas { border:1px solid black; position:absolute; /* Firefox */ top: 120px; left: 5px; } これでCanvasが2枚重なりました。何枚も重ねる場合や重ね順を変える場合にはCSSでz-indexを指定するか、スクリプトでzIndexプロパティに重ね順を設定した方がいいかもしれません。 ------------------------------------------------------------------------------------------------ ■Canvasに塗る 本書のレッスン27で、どのようにして描くかは解説しているので、その部分は省きます。変更点は以下の部分で、色を塗る部分を背面のCanvasにしているだけです。マウスイベントの取得などは前面のCanvasで行い、実際に描画するのは背面のCanvasということです。これだけで塗り絵ができます。 canvasObj.addEventListener("mousemove", function(evt){ if (!canvasObj.drawFlag){ return; } var x = evt.offsetX || evt.layerX; var y = evt.offsetY || evt.layerY; // ★ここでCanvas2に描くようにします context2.strokeStyle = canvasObj.penColor; context2.lineWidth = 20; context2.lineCap = "round"; context2.beginPath(); context2.moveTo(canvasObj.oldX, canvasObj.oldY); context2.lineTo(x, y); context2.stroke(); context2.closePath(); // ここまで canvasObj.oldX = x; canvasObj.oldY = y; }, false); 実際のプログラムは以下のようになります。ペンの色などをいろいろ変更できるようにしたり改良してみてください。 ------------------------------------------------------------------------------------------------ ■塗り絵 ------------------------------------------------------------------------------------------------ // ページの読み込みが完了したら処理をする window.addEventListener("load", function(){ // Canvasが使えるか調べる if (!window.HTMLCanvasElement){ alert("Canvasが使用できません"); return; } // Canvasの要素 var canvasObj = document.getElementById("myCanvas"); // 前面のCanvs var canvasObj2 = document.getElementById("myCanvas2"); // ★実際に塗るCanvas // 2Dコンテキストの取得 var context = canvasObj.getContext("2d"); var context2 = canvasObj2.getContext("2d"); // ★実際に塗るCanvasのコンテキストも取得 if (!context){ alert("2Dコンテキストが取得できません"); return; } // ★線画を前面のCanvasに描画する var imgObj = new Image(); imgObj.src = "images/lineart.png"; imgObj.onload = function(){ context.drawImage(imgObj, 0, 0); } // ★ペンの色を入れる canvasObj.penColor = "red"; // Canvasを塗りつぶす context2.fillStyle = "#f0f8f8"; context2.fillRect(0, 0, canvasObj.width, canvasObj.height); // 描画 canvasObj.oldX = 0; canvasObj.oldY = 0; canvasObj.drawFlag = false; canvasObj.addEventListener("mousemove", function(evt){ if (!canvasObj.drawFlag){ return; } var x = evt.offsetX || evt.layerX; var y = evt.offsetY || evt.layerY; // ★ここでCanvas2に描くようにします context2.strokeStyle = canvasObj.penColor; context2.lineWidth = 20; context2.lineCap = "round"; context2.beginPath(); context2.moveTo(canvasObj.oldX, canvasObj.oldY); context2.lineTo(x, y); context2.stroke(); context2.closePath(); // ここまで canvasObj.oldX = x; canvasObj.oldY = y; }, false); canvasObj.addEventListener("mousedown", function(evt){ canvasObj.oldX = evt.offsetX || evt.layerX; canvasObj.oldY = evt.offsetY || evt.layerY; canvasObj.drawFlag = true; }, false); canvasObj.addEventListener("mouseup", function(evt){ canvasObj.drawFlag = false; }, false); // ★ペンのカラーを設定 document.getElementById("red").addEventListener("click", function(evt){ canvasObj.penColor = "red"; }, false); document.getElementById("green").addEventListener("click", function(evt){ canvasObj.penColor = "green"; }, false); document.getElementById("blue").addEventListener("click", function(evt){ canvasObj.penColor = "blue"; }, false); }, true); ------------------------------------------------------------------------------------------------ ■塗り絵(HTML) ------------------------------------------------------------------------------------------------