ユーザーID パスワード

技術情報

  • FAQ よくある質問
  • 個人ユーザー向けサービスのお手続きについて

コード&コラム Web編 〜実践!HTML5〜

第2章 Canvas (3/3)

前へ 1 |2 |3

Canvas APIを利用したペイントツール

これまで紹介してきた2dコンテキストのメソッド、プロパティを用いてマウスの動きに合わせてピクセルを描画するペイントツールを作成してみましょう。
最初にcanvas.htmlの作成を行っていきます。


図8

図8: 初期表示


図9

図9: 線のサイズ:1、カラー:赤を選択


図10

図10: 線のサイズ:20、カラー:黄を選択


図11

図11: ラインクリアボタンクリック


キャンバスの定義

まずはCanvasの定義を行います。idをcanvasとし、widthとheightのプロパティを設定しています。また、Canvas機能非対応のブラウザに対して代替メッセージを表示するようにしています。

<canvas id="canvas" width="320" height="300">
お使いのブラウザはHTML5のCanvas要素に対応していません。
</canvas>

JSファイルの読み込み

InternetExplorer8以前のブラウザでもCanvas機能が対応できるようexcanvas.jsの読み込みを行います。また、今回はjQueryを利用する為外部JSファイルとして読み込みます。
最後に独自に作成するcanvas.jsファイルも外部ファイルとして併せて読み込みを行います。

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script type="text/javascript" src="./js/canvas.js"></script>
<!--[if IE]>
<script type="text/javascript" src="./js/excanvas.js"></script>
<![endif]-->

カラーパレットの設定

<table>タグを利用して18色のカラーテーブルを作成します。
それぞれの<td>タグにおいてCSSのstyleプロパティで背景色を設定しています。

<table>
<tr>
<td style="background-color:#000000"></td>
<td style="background-color:#808080"></td>
<td style="background-color:#c0c0c0"></td>
<td style="background-color:#ffffff"></td>
<td style="background-color:#800000"></td>
<td style="background-color:#ff0000"></td>
</tr>
<tr>
<td style="background-color:#008000"></td>
<td style="background-color:#00ff00"></td>
<td style="background-color:#808000"></td>
<td style="background-color:#ffff00"></td>
<td style="background-color:#000080"></td>
<td style="background-color:#0000ff"></td>
<tr>
</table>

線のサイズプルダウンの設置

描画する線のサイズを変更できるようプルダウンを作成します。

線のサイズ:
<select id="size">
<option value="1" selected>1</option>
<option value="10">10</option>
<option value="20">20</option>
<option value="30">30</option>
</select>

ラインクリアボタンの設置

クリックにより描画した線を消去する為のラインクリアボタンを作成します。

<input type="button" id="clear" value="ラインクリア" />

次にマウスイベントにより描画を行うcanvas.jsを作成します。

変数の定義

まずは本jsファイルで利用する変数の定義を行います。

var offset = 2;
var startX;
var startY;
var endX;
var endY;
var paint = false;
var context;

描画する線がカーソルと重ならないようoffset値を設定しています。
また、描画可否の判断を行う為にpaintフラグを設定しています。

2dコンテキストの取得

//2dコンテクストを取得
context = $("#canvas")[0].getContext('2d');

今回はjQueryを利用する為、2dコンテキストをgetElementByIdメソッドではなくjQueryを用いて取得しています。

mousedownイベント時の操作

$('#canvas').bind('mousedown', function(e) {
    paint = true;
    //位置の設定
    startX = e.pageX - offset;
    //位置の設定
    startY = e.pageY - offset;
    return false;    
});

マウスダウン発生時にpaintフラグをtrueに設定しています。
また、offset分を差し引いたマウスダウン時の座標位置を取得し、startX、startYにそれぞれ設定しています。

mousemoveイベント時の操作

$('#canvas').bind('mousemove', function(e) {
    if (paint) {
        endX = e.pageX - offset;
        endY = e.pageY - offset;
        // パスをリセット
        context.beginPath();
        // パスの始点を設定
        context.moveTo(startX, startY);
        // 直線パスの設定
        context.lineTo(endX, endY);
        // 線の終点をroundに設定
        context.lineCap = "round";
        // 線の描画
        context.stroke();
        startX = endX;
        startY = endY;
    }
});

paintフラグがONの場合のみ処理が続行されます。
mousemoveが発生した際の座標位置を取得しendX, endYに設定します。
beginPathメソッドでパスをクリアし、moveToメソッドでパスの始点を設定、lineToメソッドを用いてパスの作成を行います。
lineCapプロパティをroundに設定し、strokeメソッドで描画を実行します。
描画終了後にendX, endYの値をstartX, startYに設定することで次マウスイベントの準備を行います。

mouseupイベント時の操作

$('#canvas').bind('mouseup', function(e) {
    paint = false;
});

マウスアップが発生したタイミングで描画可否の判断を行うpaintフラグをOFFに設定します。

mouseleaveイベント時の操作

$('#canvas').bind('mouseleave', function(e) {
    paint = false;    
});

マウスがキャンバスから離れた際も同様に、描画可否の判断を行うpaintフラグをOFFに設定します。

touchstartイベント時の操作

$('#canvas').bind('touchstart', function(e) {
    paint = true;
    e.preventDefault();
    startX = e.originalEvent.changedTouches[0].pageX - offset;
    startY = e.originalEvent.changedTouches[0].pageY - offset;
});

スマートフォン用touchstartイベント発生時もmousedownと同様、paintフラグをONに設定し、タッチされた場所をstartX, startYにそれぞれ設定しています。

touchmoveイベント時の操作

$('#canvas').bind('touchmove', function(e) {
    if (paint) {
        endX = e.originalEvent.changedTouches[0].pageX - offset;
        endY = e.originalEvent.changedTouches[0].pageY - offset;
        context.beginPath();
        context.moveTo(startX, startY);
        context.lineTo(endX, endY);
        context.lineCap = "round";
        context.stroke();
        startX = endX;
        startY = endY;
    }
});

こちらもmousemoveイベントと同様の処理となります。

touchendイベント時の操作

$('#canvas').bind('touchend', function(e) {
    paint = false;
});

mouseleaveイベントやmouseupイベント発生時と同様、描画可否を判断するpaintフラグをOFFに設定します。

ラインクリアボタンクリックによる描画クリア

$('#clear').click(function(e) {
    e.preventDefault();
    context.clearRect(0, 0, $('canvas').width(), $('canvas').height());
});

idプロパティ:clearのクリックイベント発生時にclearRectメソッドを使ってキャンバスのクリアを実行します。

カラーパレットクリックによるstrokeSryleの変更

$('td').click(function(e) {
    context.strokeStyle = $(this).css('background-color');
});

htmlの各タグをクリックすることで選択された色をstrokeStyleに設定します。

サイズプルダウン選択によるlineWidthの変更

$('#size').change(function(e) {
    context.lineWidth = $(this).val();
});

id属性:sizeのチェンジイベント発生時に、変更となった値をlineWidthに設定します。

以下がcanvas.html、canvas.jsの全ソースとなります。

[canvas.html]

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name = "viewport" content = "initial-scale = 1.0, user-scalable = no" />
<title>PaintTool</title>
<style>
canvas {
    border: 1px solid #ccc;
}

td {
    padding: 5px;
    border:1px solid #cccccc;
    width:50px;
    height:50px;
}
</style>
<script type="text/javascript"
 src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script type="text/javascript" src="./js/canvas.js"></script>
<!--[if lte IE 8.0]>
<script type="text/javascript" src="./js/excanvas.js"></script>
<![endif]-->
</head>
<body>
<canvas id="canvas" width="300" height="250">
お使いのブラウザはHTML5のCanvas要素に対応していません。
</canvas>
<div style="border:solid 1px #cccccc;width:300px">
<table>
<tr>
<td style="background-color:#000000"></td>
<td style="background-color:#808080"></td>
<td style="background-color:#c0c0c0"></td>
<td style="background-color:#ffffff"></td>
<td style="background-color:#800000"></td>
</tr>
<tr>
<td style="background-color:#008000"></td>
<td style="background-color:#00ff00"></td>
<td style="background-color:#808000"></td>
<td style="background-color:#ffff00"></td>
<td style="background-color:#000080"></td>
<td style="background-color:#0000ff"></td>
</tr>
</table>

線のサイズ:
<select id="size">
<option value="1" selected>1</option>
<option value="10">10</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="40">40</option>
<option value="50">50</option>
</select>

<input type="button" id="clear" value="ラインクリア" />

</div>
</body>
</html>

[canvas.js]

$(function() {
    var offset = 2;
    var startX;
    var startY;
    var endX;
    var endY;
    var paint = false;

    //2dコンテクストを取得
    var context = $("#canvas")[0].getContext('2d');
    //マウスイベント   mousedown
    $('#canvas').bind('mousedown', function(e) {
        paint = true;
        startX = e.pageX - offset;
        startY = e.pageY - offset;
        return false;
    });

    //マウスイベント - mouseup
    $('#canvas').bind('mouseup', function(e) {
        paint = false;
    });

    //マウスイベント - mouseleave
    $('#canvas').bind('mouseleave', function(e) {
        paint = false;
    });

    //マウスイベント - mousemove
    $('#canvas').bind('mousemove', function(e) {
        if (paint) {
        endX = e.pageX - offset;
        endY = e.pageY - offset;
    
        context.beginPath();
        context.moveTo(startX, startY);
        context.lineTo(endX, endY);
        context.lineCap = "round";
        context.stroke();
        startX = endX;
        startY = endY;
        }
    });

    // *** スマートフォン用 *******************/
    // タッチイベント - touchstart
    $('#canvas').bind('touchstart', function(e) {
        paint = true;
        e.preventDefault();
        startX = e.originalEvent.changedTouches[0].pageX -offset;
        startY = e.originalEvent.changedTouches[0].pageY -offset;
    });

    // *** スマートフォン用 *******************/
    // タッチイベント - touchmove
    $('#canvas').bind('touchmove', function(e) {
        e.preventDefault();
        if (paint) {
            endX = e.originalEvent.changedTouches[0].pageX - offset;
            endY = e.originalEvent.changedTouches[0].pageY - offset;
            context.beginPath();
            context.moveTo(startX, startY);
            context.lineTo(endX, endY);
            context.lineCap = "round";
            context.stroke();
            startX = endX;
            startY = endY;
        }
    });

    // *** スマートフォン用 *******************/
    // タッチイベント   touchend
    $('#canvas').bind('touchend', function(e) {
        paint = false;
    });

    // クリア
    $('#clear').click(function(e) {
        e.preventDefault();
        context.clearRect(0, 0, $('canvas').width(), $('canvas').height());
    });

    // 色選択
    $('td').click(function(e) {
        context.strokeStyle = $(this).css('background-color');
    });

    // サイズ選択
    $('#size').change(function(e) {
        context.lineWidth = $(this).val();
    });
});  

(文責:株式会社ベストクリエイト)

サンプルコード

第1章
Audio/Video

第2章
Canvas

第3章
Photo Gallery

第4章
神経衰弱ゲーム