Skip to content

お絵描きアプリで学ぶHTML5のCanvas超速入門 #1.5 JavaScriptで描いた絵をサーバを使わずにセーブする!?

こんにちは。UEIの近藤です。
shi3zさんに言われてちょっと連載に補足します。

まず、相変わらず雑な迅速なコーディングに定評のあるshi3z編集チョですが、なんかちょっとマウスカーソルの位置と実際に描画される場所がずれてます。これはヘンなので修正したいと思います。

修正したコードは以下の通り


var canvas,canvasDiv;
var x=0,y=0;
function onLoad() {
    canvasDiv = document.getElementById("canvas0");
    canvas =document.createElement("canvas");
    canvas.width=320;
    canvas.height=480;
    canvasDiv.appendChild(canvas);
    ctx = canvas.getContext('2d');

    canvasRect = canvas.getBoundingClientRect(); //A キャンバスの位置を取得

    canvas.addEventListener("touchmove", function(event){
        mouseX = event.touches[0].pageX - canvasRect.left; //B キャンバスのX座標を引く
        mouseY = event.touches[0].pageY - canvasRect.top; //C キャンバスのY座標を引く
        ctx.beginPath();
        ctx.moveTo(x,y);
        ctx.lineTo(mouseX, mouseY);
        ctx.stroke();
        x =mouseX;
        y =mouseY;
        event.preventDefault();
    }, false);
    document.addEventListener("touchstart", function(event){
        x = event.touches[0].pageX - canvasRect.left;//D キャンバスのX座標を引く
        y = event.touches[0].pageY - canvasRect.left;//E キャンバスのY座標を引く
        }, false);
    document.addEventListener("touchend", function(){
        }, false);
}

実はこのプログラムは、もともと画面のなかに、canvasの領域を作るところがミソでした。
実はこのcanvasの位置は、ビミョーにずれてます。

Safariの「環境設定」で「開発メニューを表示する」をオンにすると、JavaScriptの開発に便利な機能が追加されます。

この開発メニューから、「Webインスペクタを表示」を選ぶと、HTML要素がどのように分かれているかハイライト表示させて確認することかできて非常に便利です。

これでcanvas要素を確認すると、ビミョーにずれていることがわかります。

このズレている分を取得するために、まずAの行でキャンバスのページ内座標を取得しています。

この図のように、canvasがページ内座標でどのような位置にあるかをcanvas.getBoundingClientRect関数で調べることができます。

この関数の返り値canvasRectはオブジェクトになっていて、topでページ内Y座標を、leftでページ内x座標を取得することができます。

マウスまたはタッチの動きそのものは、canvasの中に描画されるので、このpageX、pageYからcanvasの左上座標ぶん引いてずらしてやると、きっちり描画されます。

さて、気持ち悪いズレがなおったところで、本題です。

どれだけ奇麗に絵を描いても、これ、アプリ終了しちゃうと消えちゃうんですよね。
それはあまりに勿体ない。

さりとて、canvas要素はそのままだとiPhoneのブラウザのデフォルトの動作、長押し⇒画像を保存でセーブすることもできません。

そこでこの関数を加えます。


function saveCanvas() {
    var strDataURI = canvas.toDataURL("image/jpeg"); //A canvasをJPEGに変換
    var temp = "

<img src="
\""+strDataURI+"\"" alt="" width="\"310px\"" />"; //B データをつくる
    window.open("
data:text/html;base64,"+ window.btoa(temp)); //C 新しいウィンドウで画像ファイルを開く
}

この関数は、いくつか重要なことをします。
まずAの行。canvas.toDataURLでcanvasの内容をJPEGに変換しています。
こんな便利な命令があるあたりが最近のJavaScriptの恐ろしいところです。

こうしてcanvasの内容をJPEG化し、しかもそれを文字列で貰うことができます。
続くBの行(長いですが一行です)で、ひとつ呪文のようなWebページを作ります。

そしてCの行、このWebページを別ウィンドウとして開くわけです。

window.open関数には、本来URLを渡しますが、通常よくつかわれるのはhttp://で始まるURLです。ここをdata:text/html;base64で始めると、なんとデータを直接渡すことかできるのです。

iPhoneでは、このURLの先頭にhttp://以外の文字を指定することで、他のアプリを起動したり、いろいろなことができます。この仕組みをURLスキームと呼びます。

さまざまなURLスキームがありますが、ここではデータを直接渡しています。

こうして開かれたウィンドウの画像は、単なるJPEGファイルです。
ここで画像を長押しすることで保存したりできます。

実際にやってみるには、このsaveCanvas関数を呼び出すボタンを設置する必要があります。
onLoad関数に少し手を加えましょう。


    canvasDiv = document.getElementById("canvas0");
    canvasDiv.innerHTML ="
<input onclick="
saveCanvas()" type="button" value="SAVE" />"; //A SAVEボタンを追加
    canvas =document.createElement("canvas");

canvasDivにcanvasを追加する直前にSAVEボタンを追加しています。

onclickのときにsaveCanvasを呼び出しているわけです。
これで準備完了。実際にやってみてください。

このテクニックは非常に強力で、メールさせることもできます。


function mailCanvas() {
    var strDataURI = canvas.toDataURL("image/jpeg");
    var temp = "

<img src="
\""+strDataURI+"\"" alt="" width="\"310px\"" />";;
    location.href = "
mailto:?body=" + temp; //A メーラーを開く
}

Aの行でメーラーを開くと、自動的にこの画像が挿入されたメール画面が開きます。

SAVEボタンと同様にMAILボタンも付け加えてみた

実際に試してみましょう。
さきほどのSAVEボタンと同じ要領でMAILボタンを追加します。


    canvasDiv = document.getElementById("canvas0");
    canvasDiv.innerHTML ="
<input onclick="
saveCanvas()" type="button" value="SAVE" />";
    canvasDiv.innerHTML +="
<input onclick="
mailCanvas()" type="button" value="MAIL" />";
    canvas =document.createElement("canvas");

適当な絵を描いて、MAILボタンを押すと下のような画面になります。

MAILボタンを押すとメーラーが立ち上がり、画像として添付される

URLスキームを使うとこんな面白いことができるんです、という紹介でした。
ちなみにsaveCanvas関数とmailCanvas関数はMac上のSafariでも正しく動作します。

Macで動作するサンプルを以下に示します。

http://chephes.sakura.ne.jp/canvas2/

このコードはMITライセンスで提供されているhttp://miniapps.co.uk/のソースを改造したものです。

データスキームは応用範囲が広く、たとえばJavaScriptでzipファイルを作成して渡したり、といったこともできます。

昔はbit.lyでもデータスキームが使えたのでいろいろと楽しいこともできたのですが・・・。
今はダメなようです。

ではまた機会があればお会いしましょう。
近藤誠でした。

文・近藤誠

このエントリーをはてなブックマークに追加
はてなブックマーク - お絵描きアプリで学ぶHTML5のCanvas超速入門 #1.5 JavaScriptで描いた絵をサーバを使わずにセーブする!?
Post to Google Buzz
Share on GREE

Related posts:

  1. お絵描きアプリで学ぶHTML5のCanvas超速入門 #2 iPhoneで行こう
  2. お絵描きアプリで学ぶHTML5のCanvas超速入門 #1
  3. shi3z式ゲームプログラミング #6 覚えておくといいテクニック
  4. 見た目でゴマカす超速Webアプリ開発 #1
  5. shi3z式ゲームプログラミング入門 #4 バナナと配列

Facebook comments:

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*