Fabric.jsの手書き入力機能で校庭に落書きする

3 min読了の目安(約3300字TECH技術記事

ゆるWeb勉強会@札幌 Advent Calendar 2020 21日目の記事です。

前置き

God kveld. DE-TEIUです。
今回はFabric.jsで遊んでみました。

成果物

突然ですが、大体どこの学校でも、倉庫にこーいうのがあるじゃないですか。
「ライン引き」「白線引き」とかいうやつですね。

誰しも子供の頃、これを使って校庭にめっちゃ落書きしたいと思った事があると思います。
今回はその夢を叶えるWebアプリを開発しました。
(スマートフォンでもPCでも利用可能)

Ground The World

校庭に落書きが

できたと思います。

解説

以下、実装の解説等です。

Fabric.jsで手書き入力

Fabric.jsとは、HTML5のcanvas要素の機能を拡張するライブラリです。
今回はその中の、手書き入力機能を使用していきます。

インストール方法(npmを使う場合)

npm install fabric

使う際は、まずHTML内にcanvas要素を追加

<canvas id="canvas"></canvas>

JavaScriptでFabric.jsを読み込んでcanvasに適用

import { fabric } from "fabric";

window.onload = () => {
  const canvas = new fabric.Canvas("canvas", {
    isDrawingMode: true // 手書き入力ON
  });
  
  setBrush(canvas);// ペンの色とか種類を指定(以下に解説)

  setBackgroundImage(canvas);// 背景画像を設定(以下に解説)
};

これだけでcanvasに手書き入力ができるようになります。
次に、入力時のブラシの色や種類を指定してみます。

const setBrush = (canvas) => {
  canvas.freeDrawingBrush = new fabric['SprayBrush'](canvas); // スプレーブラシを指定
  if (canvas.freeDrawingBrush) {
    const brush = canvas.freeDrawingBrush;
    brush.color = 'white'; // ブラシの色指定(#FFFFFFやrgb(255,255,255)等の書き方でも可)
    if (brush.getPatternSrc) {
        brush.source = brush.getPatternSrc.call(brush);// 設定を反映
    }
    brush.width = 10;// 線の太さを指定
    brush.shadow = new fabric.Shadow({ // 線に影をつける
        blur: 3,
        offsetX: 0,
        offsetY: 0,
        affectStroke: true,
        color: 'white',
    });
  }
};

そしてcanvasに背景を設定してみます。
指定した画像を読み込んでcanvasの大きさに合わせて拡大(縮小)します。
(今回は画像の縦横比は維持してません)

const setBackgroundImage = (canvas) => {
    fabric.Image.fromURL('画像ファイルのパス', (img) => {
        img.set({
            opacity: 1,// 透明度
            scaleX: canvas.width / img.width,// X軸の拡大率
            scaleY: canvas.height / img.height,// Y軸の拡大率
        });
        canvas.setBackgroundImage(img, 
          canvas.requestRenderAll.bind(canvas) );// 画像を背景に設定
    });
};

Canvasを画像として保存する

canvasに描いた絵を、「せっかくだから画像として保存したい」なんて思う事があると思います。

まずはHTMLに以下こんな要素を追加しましょう

<button id="btn-save">保存</button>
<a id="link-download" class="hidden" download="ground.png" target="_blank">hide</a>

link-downloadはスタイルで非表示にしておきます

.hidden {
  display:none;
}

JavaScriptで保存ボタンを押した時のイベントを設定

document.getElementById("btn-save").addEventListener("click",()=>{
  const link = document.getElementById('link-download');
  const dataurl = canvas.toDataURL();// canvasのピクセルデータをDataURLに変換
  link.href = dataurl;// DataURLをダウンロードリンクに設定
  link.click();// ダウンロード実行
});

これでダウンロードできます。
※iOSのSafariで実行した場合、ダウンロードされず別ウィンドウで画像を表示する挙動になります。ChromeやEdgeやFirefoxではダウンロードされます。ご注意ください。

まとめ

Web上で何かしらの手書き入力がしたい、という要件があった際にはFabric.jsの採用を検討してみてはいかがでしょうか。
また、Fabric.jsには今回ご紹介した手書き入力以外にも、画像をアニメーションさせる、フィルターをかける、ドラッグで移動&スケーリングさせるなど様々な機能が搭載されているので興味がある方は調べてみると良いと思います。

参考資料

AngularとFabric.jsでお絵描き - Qiita
Free drawing | Fabric.js Demos