Javascript プログラミング

fabric.jsでペン習字練習アプリを作った

コロナでヒマなので利き手じゃない方で字を書く練習をはじめた

私は左利きなのですが、コロナでヒマなので右手で文字を書く練習を始めてみました。

紙とペンを使うともったいないのでとりあえずiPadにスタイラスペンで適当な文字を書いていました。

それだけでもそこそこ楽しいのですが、しばらく練習しているとやっぱりお手本が欲しくなるんですよね。

適当に書くよりも、ちゃんとした文字をなぞって練習したほうがうまくなるような気がします。

左手の悪筆はもう直らないと思うので右手は美文字になりたい。

AppStoreでペン習字アプリとか探して見ましたが、どうも気に入るものがありません。

そこでちょうどfabric.jsでお絵描きアプリを作ったところなのでその応用でペン習字の練習アプリを作ってみました。

アプリのページ

ソースコード(github)

 

ブラウザ上でお手本画像をなぞって練習できる

図のように薄い画像でお手本が表示され、その上をペンでなぞって練習できます。

 

一応最初は五十音のひらがなの練習画像を用意しました。

練習画像はメニューから切り替えられます。

 

「クリア」ボタン押すとお手本はそのままで自分で書いた文字だけを消せます。

 

再読み込みボタンはタブレットの縦横の向きを変更したり、ウィンドウをリサイズしたときにお手本のサイズを画面に合わせるために使います。

画面の向きを変えると画像がずれる

 

再読み込みで修正される

 

お手本画像はcanvas.setBackgroundImageで設定

プログラム的には特に難しいことはしていません。

お手本の画像はグラフィックソフトで作ったものをPNGで保存しました。

画像はfabric.jsのfabric.Image.fromURLで読み込んで、 canvas.setBackgroundImageで貼り付けています。

canvas.setBackgroundImageのオプションでopacityを0.2にしてお手本画像を薄くしています。

手書きはfabric.jsのfree drawing機能を使っています。

全体のコードはこんな感じです。短いのでhtmlだけで済ませています。

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>スタイラスペン習字練習帳</title>
</head>

<style>
  #canvas-container {
    width: 100%;
    height: 100%;
  }

  #controller {
    text-align: center;
    margin-bottom: 0;
  }

  #reload {
    margin-left: 20px;
  }

  #otehon_selecter {
    margin-left: 20px;
  }
</style>

<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.2.0/fabric.min.js"></script>
  <p id="controller">
    <button id="delete">クリア</button>
    <select id="otehon_selecter">
      <option value="1.png">あ〜さ行</option>
      <option value="2.png">た〜は行</option>
      <option value="3.png">ま〜わ行</option>
      <option value="4.png">すべて(小)</option>
    </select>
    <button id="reload">再読み込み</button>
  </p>
  <div id="canvas-container">
    <canvas id="canvas"></canvas>
  </div>


  <script>
    document.addEventListener('DOMContentLoaded', function () {
      const OTEHON_DIR = "./otehon/";
      const PEN_WIDTH = 5;
      const PEN_COLOR = "rgb(0,0,0)";
      let otehon_file = "1.png";
      const canvas_element = document.getElementById("canvas");
      canvas_element.width = document.documentElement.clientWidth;
      canvas_element.height = document.documentElement.clientHeight - 50;

      const canvas = new fabric.Canvas('canvas');

      loadOtehon(otehon_file);


      canvas.freeDrawingBrush.color = PEN_COLOR;
      canvas.freeDrawingBrush.width = PEN_WIDTH;
      canvas.isDrawingMode = true;

      document.getElementById("delete").addEventListener("click", cleanCanvas);

      var selecter = document.getElementById('otehon_selecter');

      selecter.onchange = function () {
        otehon_file = this.value;
        loadOtehon(otehon_file);
        cleanCanvas();
      }

      function loadOtehon(filename) {
        const filePath = OTEHON_DIR + filename;
        fabric.Image.fromURL(filePath, function (otehonImg) {
          if (canvas.width / canvas.height > otehonImg.width / otehonImg.height) {
            otehonImg.scaleToHeight(canvas.height);
          } else {
            otehonImg.scaleToWidth(canvas.width);
          }
          canvas.setBackgroundImage(otehonImg, canvas.renderAll.bind(canvas), {
            left: (canvas.width - otehonImg.width * otehonImg.scaleX) / 2,
            opacity: 0.2
          });
        });
      }

      function cleanCanvas() {
        canvas.getObjects().forEach(element => {
          canvas.remove(element);
        });
        canvas.requestRenderAll();
      }

      document.getElementById("reload").addEventListener("click", () => {
        console.log("reload");
        window.location.reload();
      });


    });
  </script>
</body>

</html>

画像を差し替えれば、文字だけでなく、絵の練習なんかにも使えると思います。

まだ全然右手で書けるようにはなっていませんが、利き手じゃないほうの手を使うとなんだかちょっと脳みそがぐるぐるして面白いです。

 

-Javascript, プログラミング
-