HTML/CSS+JavaScriptでiPhone/iPadアプリを開発できるNimbleKit。前回まではNimbleKit独自のAPIを使ってアプリを開発する方法を紹介してきましたが、NimbleKitを使うとHTML/CSS+JavaScriptで作ったWebアプリケーションもiOSアプリとしてパッケージ化できます。NimbleKit編の最終回は、HTML5 Canvasを使ったお絵かきツール「シンプルペイント」をiPhoneアプリに変換する方法を紹介します。
- 古籏一浩のJavaScriptラボ 第31回「HTML5のCanvasで作る、Flash不要のお絵かきツール」
- http://ascii.jp/elem/000/000/513/513377/
シンプルペイントはPCのブラウザー向けに作ったWebアプリですので、iPhone/NimbleKitでは実装が難しい機能もあります。そこでiPhoneアプリにするにあたって、以下の点を変更します。
- iPhoneの画面サイズに合わせてCanvasの描画領域を調整
- ブラシサイズは固定
- ブラシのカラーはNimbleKitのスライダーで設定可能
- 設定したブラシのカラーは自動的にプレファレンス(設定)に保存。次回起動時にカラー設定を復元
最低限の機能を移植する
最初に、シンプルペイントのHTMLをiPhone用に変更します。canvas要素のwidth属性とheight属性でCanvasの描画領域を320×320pxに設定し、canvas要素の下に描画色を示すカラーバー領域をdiv要素で用意します。HTMLの最後に、script要素でシンプルペイントのメイン処理を記述したスクリプト「draw.js」 を読み込ませます。draw.jsファイルはこれまで同様、Resourcesフォルダに入れておきましょう。
draw.jsは、第31回で掲載したサンプルから保存機能やブラシのカラー選択機能を削除したものです。iPhoneではイベントオブジェクトのtouches配列に、タッチされた座標が入っていますので、X,Y座標を求める処理を以下のように変更しています。pageX, pageYはページの左上を基準にした座標です。
●PC用
var x = e.clientX; var y = e.clientY;
↓
●iPhone/iPad用
var x = e.touches[0].pageX; var y = e.touches[0].pageY;
標準では画面上をドラッグするとページがスクロールしてしまうので、以下のスクリプトを追加して画面を固定します。
document.ontouchmove = function(evt){
evt.preventDefault();
}
ここまでをまとめたのがサンプル1です。Canvas上を指でなぞると赤い線で絵が描けます。
■サンプル1[HTML]
<html> <head> <meta name = "viewport" content = "initial-scale = 1.0, user-scalable = no" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <script type="text/javascript" src="NKit.js"></script> <style> body { margin:0; padding: 0; background-color:black; } canvas { background-color: white; } </style> </head> <body> <canvas id="myCanvas" width="320" height="320"></canvas> <div id="stat"></div> <script type="text/javascript" src="js/draw.js"></script> </body> </html>
■サンプル1[draw.js]
var drawData = { drawFlag : false, oldX : 0, // 直前のX座標を保存するためのもの oldY : 0, // 直前のY座標を保存するためのもの brushSize : 4, // ブラシサイズ penColor : "rgba(255,0,0,1)" } var can = document.getElementById("myCanvas"); can.addEventListener("touchmove", function draw(e){ if (!drawData.drawFlag) return; var x = e.touches[0].pageX; var y = e.touches[0].pageY; document.getElementById("stat").innerHTML = drawData.oldX+","+drawData.oldY; var can = document.getElementById("myCanvas"); var context = can.getContext("2d"); context.strokeStyle = drawData.penColor; context.lineWidth = drawData.brushSize; context.lineJoin= "round"; // 連結部分を丸にする context.lineCap = "round"; context.beginPath(); context.moveTo(drawData.oldX, drawData.oldY); context.lineTo(x, y); context.stroke(); context.closePath(); drawData.oldX = x; drawData.oldY = y; }, true); can.addEventListener("touchstart", function(e){ drawData.drawFlag = true; drawData.oldX = e.touches[0].pageX; drawData.oldY = e.touches[0].pageY; document.getElementById("stat").innerHTML = drawData.oldX+","+drawData.oldY; }, true); can.addEventListener("touchend", function(){ drawData.drawFlag = false; }, true); // デフォルトのイベントを禁止 document.ontouchmove = function(evt){ evt.preventDefault(); }