FabricJS

【JavaScript】Fabric.jsで矩形にオブジェクトIDをつける

Fabric.jsはcanvas上での様々な操作を簡単に実装できるライブラリでとても便利。しかし、基本的にはcanvas上での描画のためのライブラリであるため、canvas以外の要素との連携や矩形オブジェクトを個別に操作していくのが少し苦手。

矩形をIDで参照できるようにする。

Fabric.jsの読込設定

fabric.jsはCDNがあるので、それを使用する。ソースをDLしてもどちらでもいい。

canvasの設定もしておく。

html
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.3.2/fabric.min.js"></script>
<!-- canvasを設定 -->
<canvas class="imageCanvas" id="imageCanvas"></canvas>

 

Canvasの基本設定

画面ロード時にcanvasの基本設定を行う。

キャンバスのサイズはデフォルトだと300(width)×150(height)が設定されるので、適当にサイズを設定する。

今回は長方形の矩形オブジェクトを作成していくため、isDrawingMode に falseを設定して、フリーハンドの描画はできないように設定する。

/*
 * グローバル変数の宣言
 */
var canvas;

//矩形オブジェクトに付与するIDのカウンター
var cnt;

//描画処理用のフラグと座標
var startFlg;
var startX;
var startY;
var endX;
var endY;

//矩形のIDとインデックス対応付け用配列
var arrayRect = [];

const OBJ_NAME = "objNo";

/*
 * 画面ロード時に実行される処理
 */
function load(){
    canvas = new fabric.Canvas('imageCanvas');

    //キャンバスサイズの設定
    canvas.setWidth(800);
    canvas.setHeight(800);

    //フリー描画禁止
    canvas.isDrawingMode = false;

    //矩形オブジェクトを一意に識別するためのカウンタ
    cnt = 0;

    //描画操作の開始確認用フラグと座標の初期化
    startFlg = false;
    startX = 0;
    startY = 0;
    endX = 0;
    endY = 0;

    //canvas関連のイベントリスナー登録
    canvas.on('mouse:down', function(e) { mousedown(e); });
    canvas.on('mouse:move', function(e) { mousemove(e); });
    canvas.on('mouse:up', function(e) { mouseup(e); });
}

window.addEventListener('DOMContentLoaded', load, false);


function countUpCnt(){
    //cntを1増やす
    cnt = cnt + 1;
}

 

キャンバスにはマウスボタンによるイベントリスナーが用意されているため、マウスボタン押下時、マウス移動時、マウスボタンを離した時の処理をそれぞれ追加する。

各マウスイベント処理

マウスボタン押下時の処理

マウスを押下した点が矩形の描画開始点になるため、座標を取得する。

/*
 * Mousedown
 * キャンバス内でマウスボタンを押下した際の処理
 */
function mousedown(e) {
    //描画処理を開始する。
    //マウスのポインター情報を取得
    let mouse = canvas.getPointer(e.e);

    //描画開始フラグをtrueに設定
    startFlg = true;

    //マウスの座標を開始座標に設定
    startX = mouse.x;
    startY = mouse.y;
}
 

startedは描画処理を行う際のフラグとして使用する。

マウスボタン押下中の処理

mousemoveでstartedフラグを判定することで、例えば、キャンバスの範囲外から範囲選択が開始された場合等は、矩形が描画されないようにしている。

/*
 * Mousemove
 * キャンバス内でマウスボタンを押下しながらマウスを移動させている場合の処理
 */
function mousemove(e) {

    //startFlgがfalseの場合、描画処理は行わない
    if(!startFlg) {
        return false;
    }
}

 

マウスボタンを離した際の処理

マウスボタンを離した際の処理は以下の通り。

/*
 * Mouseup
 * キャンバス内でマウスボタンを押下した状態から離した場合の処理
 */
function mouseup(e) {

    //描画処理が開始されている場合は長方形を描画する。
    if(startFlg) {
        //マウスボタンを離した座標を取得
        let mouse = canvas.getPointer(e.e);

        //矩形(長方形)描画
        let obj = new fabric.Rect({
            id: OBJ_NAME + cnt,        //ここでidを設定する
            left: startX,
            top: startY,
            width: mouse.x - startX,
            height: mouse.y - startY,
            //塗りつぶしや枠線、選択可否の設定
            fill: '',
            stroke: 'blue',
            strokeWidth: 2,
            selectable: false
        });

        canvas.add(obj);

        //オブジェクトIDを配列に保存しておく
        arrayRect.push(OBJ_NAME + cnt);

        canvas.renderAll();
        canvas.calcOffset();
        console.log("ID:" + obj.id + " 開始X:" + startX + " 開始Y:" + startY +
                " 終了X:" + mouse.x + " 終了Y:" + mouse.y);
        console.log(arrayRect);

        //IDカウンターをインクリメント
        countUpCnt();
        //描画開始フラグをFalseに戻す
        startFlg = false;
    }
}

 

長方形の描画について、originはデフォルトでtop、leftなので、それぞれの値を設定。

幅と高さも始点と終点から計算して設定。X座標、Y座標の始点と終点を指定するのではなく、幅と高さを指定する必要があるのは、originがcenterに設定することも可能なため。

ちなみにwidth、heightの値はマイナス(右下から左上に向かって描画した場合等)でも、ちゃんと絶対値が幅、高さとして設定される。

キャンバス上のオブジェクトはcanvas.item(index)でしか指定できないため、オブジェクトのIDとitemのindexを対応させるために、arrayRect.push(OBJ_NAME + cnt)で配列にオブジェクトIDとindexを保存する。

矩形オブジェクトIDからのオブジェクト操作

オブジェクトIDからオブジェクトを操作する場合の例は以下の通り。

    //オブジェクトIDの設定
    const objId = "objNo3"

    //オブジェクトIDから対象の矩形オブジェクトを取得
    let targetRect = canvas.item(arrayRect.indexOf(objId));

    targetRect.set({stroke: 'blue'});

 

オブジェクトIDからarrayRectのindexを取得する。

そのindexはcanvas.itemのindexに対応するように保存しているため、オブジェクトIDからキャンバス上の矩形オブジェクトが取得可能となる。

ハマりそうな注意点

あくまでキャンバス上のオブジェクトはcanvas.item経由でしか参照できない。オブジェクトIDを設定しても、そこから直接操作ができないのは残念。

canvas.itemはキャンバス上にオブジェクト(長方形、円、フリーハンド描画、画像等)を通以下する度にインクリメントされていくため、オブジェクトIDと canvas.item のインデックスの対応付けをしっかりと管理しておく必要がある。