canvasタグを使ってブラウザ上でお絵描きアプリを作る

JavaScript


ブラウザ上でのお絵描きは、HTML5の<canvas>タグを使って描画エリアを準備し、マウス操作をJavaScriptで制御をおこなうことで可能になります。


今回は、canvasタグを使ってブラウザ上でお絵描きをおこなう方法を紹介します。

JavaScriptでマウスの動きを制御して、canvasタグ上にお絵描きをおこないます。


HTMLとJavaScriptだけで、機能を実現することができます。


環境情報


  • ブラウザ:Chrome81
  • JQuery:JQuery2.2.4

サンプルプログラム


早速ですが、サンプルプログラムを紹介します。

紹介しているHTMLとJavaScriptをそのままコピペして使って頂ければ、基本的な機能をそなえたお絵描きアプリがブラウザ上で実現できます。


サンプルプログラムで動作するお絵描きアプリは、以下のURLから起動できます。


HTMLとJavaScriptは以下になります。


  • HTML
<body>
    <div>
        <canvas id="canvas" style="border:1px solid gray;"></canvas>
    </div>
    <div>
        <input type="button" id="undo" name="undo" value="undo">
        <input type="button" id="redo" name="redo" value="redo">
    </div>
</body>

  • JavaScript
//
// JavaScriptのグローバル変数群
//
var CANVAS_SIZE;
var undoDataStack = [];
var redoDataStack = [];
var mouseDown = false;

$(function() {
    //
    // 画面読み込み時のロード処理
    //
    $(document).ready(function(){

        // キャンバスのサイズを設定
        $('#canvas').css('width', '600px');
        $('#canvas').css('height', '600px');

        // キャンバスの属性を設定
        canvas = document.getElementById('canvas');
        canvas.width = 600;
        canvas.height = 600;
        CANVAS_SIZE = canvas.clientWidth;

        // 描画開始 → 描画中 → 描画終了
        canvas.addEventListener('mousedown', startDraw, false);
        canvas.addEventListener('mousemove', drawing, false);
        canvas.addEventListener('mouseup', endDraw, false);
    });

    //
    // undo
    //
    $("#undo").click(function() {

        if (undoDataStack.length <= 0) {
            return;
        }

        canvas = document.getElementById('canvas');
        context = canvas.getContext('2d');
        redoDataStack.unshift(context.getImageData(0, 0, canvas.width, canvas.height));

        var imageData = undoDataStack.shift();
        context.putImageData(imageData, 0, 0);
    });

    //
    // redo
    //
    $("#redo").click(function() {

        if (redoDataStack.length <= 0) {
            return;
        }

        canvas = document.getElementById('canvas');
        context = canvas.getContext('2d');
        undoDataStack.unshift(context.getImageData(0, 0, canvas.width, canvas.height));

        var imageData = redoDataStack.shift();
        context.putImageData(imageData, 0, 0);
    });
});

//
// 描画開始
//
function startDraw(event){

    // 描画前処理をおこないマウス押下状態にする。
    beforeDraw();
    mouseDown = true;

    // クライアント領域からマウス開始位置座標を取得
    wbound = event.target.getBoundingClientRect() ;
    stX = event.clientX - wbound.left;
    stY = event.clientY - wbound.top;

    // キャンバス情報を取得
    canvas = document.getElementById("canvas");
    context = canvas.getContext("2d");
}

//
// 描画前処理
//
function beforeDraw() {

    // undo領域に描画情報を格納
    redoDataStack = [];
    canvas = document.getElementById('canvas');
    context = canvas.getContext('2d');
    undoDataStack.unshift(context.getImageData(0, 0, canvas.width, canvas.height));
}

//
// 描画中処理
//
function drawing(event){

    // マウスボタンが押されていれば描画中と判断
    if (mouseDown){
        x = event.clientX - wbound.left;
        y = event.clientY - wbound.top;
        draw(x, y);
    }
}

//
// 描画終了
//
function endDraw(event){

    // マウスボタンが押されていれば描画中と判断
    if (mouseDown){
        context.globalCompositeOperation = 'source-over';
        context.setLineDash([]);
        mouseDown = false;
    }
}

//
// 描画
//
function draw(x, y){
    canvas = document.getElementById("canvas");
    context = canvas.getContext("2d");
    context.beginPath();
    context.strokeStyle = "black";
    context.fillStyle = "black";
    context.lineWidth = 2;
    context.lineCap = "round";

    context.globalCompositeOperation = 'source-over';
    context.moveTo(stX,stY);
    context.lineTo(x,y);
    context.stroke();
    stX = x;
    stY = y;
}

HTMLの構成


HTMLはとてもシンプルです。
HTML5の<canvas>タグを定義しているだけ、です。

<canvas id="canvas" style="border:1px solid gray;"></canvas>

<canvas>タグはHTML5から追加されたHTMLタグになります。
2Dのグラフィックを表示することができるので、HTMLとJavaScriptでゲームやグラフィックデザインをおこなうことができます。


ブラウザ上でのゲームは、ほぼ全てこの技術が使われています。


JavaScriptの構成


ポイントは2つありまして、1点目は描画の基本処理。


描画開始 → 描画中 → 描画終了 の3段階で処理をわけています。
イベントの検知は、JQueryのイベントリスナーを使用しています。


// 描画開始 → 描画中 → 描画終了
canvas.addEventListener('mousedown', startDraw, false);
canvas.addEventListener('mousemove', drawing, false);
canvas.addEventListener('mouseup', endDraw, false);

「mousedown(左クリック開始)」のイベントを「startDraw」ファンクションで処理しています。
クリックした位置を算出し、描画開始を認識します。


「mousemove(マウス移動)」のイベントを「drawing」ファンクションで処理しています。
マウス移動に従って、canvas上に線を描画しています。


「mouseup(左クリック終了)」のイベントを「endDraw」ファンクションで処理しています。
左クリックを終了した位置が描画の終了位置と認識します。


もう一つのポイントとしてはUNDO・REDOです。
UNDOはやり直し、REDOはやり直しのやり直し、です。


仕組みは簡単です。
グローバル変数に「undoDataStack」「redoDataStack」を準備し、この領域にデータを格納することでUNDO・REDOを実現しています。


var undoDataStack = [];
var redoDataStack = [];

描画終了したら「undoDataStack」にデータを格納し、UNDOをやったら「redoDataStack」にデータを格納します。
UNDO・REDOの操作をおこなったら、この「undoDataStack」「redoDataStack」領域からデータを取り出し、画面表示をおこないます。


まとめ


いかがでしたでしょうか?


<canvas>タグを使えば、簡単にブラウザ上でお絵描きができることがわかって頂けたかと思います。
今回は紹介しきれませんでしたが、色の指定や図形の指定もおこなうことができます。
ぜひお試しください。