Electron＋Canvas＋WebGL＋Reactのお絵描きツールの進捗2022

この記事は [Web グラフィックス Advent Calendar 2022](https://qiita.com/advent-calendar/2022/webgraphics) の25目の記事です。

# はじめに

何年か前からElectron＋Canvas＋WebGL＋Reactでベクター系お絵かきツールを作っていて、毎年アドベントカレンダーで進捗報告をしています。

[ソースコード (GitHub warotarock/manual_tracing_tool)](https://github.com/warotarock/manual_tracing_tool)
[ライブデモ (GitHub Pages)](https://warotarock.github.io/manual_tracing_tool/dist/) (バグ多いです)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59191/5429feae-d686-6d9b-a45a-ed19c430b3ed.png)

去年は何をしたんだったかなーと去年のアドベントカレンダーを見直してみると…デッサン人形やパレットの機能を拡充したいと書いていました。

うむ、全くやってない！

「自分で使うだけでもいい」とも書きましたが、書いて投稿した直後に風呂に入って一息ついたとき、「いや、やっぱりそれじゃ自己満足だ」と思いなおしました。やっぱり多くの人に使ってもらえるもの、そしてプロを自負するからには収入にもつながるものを作ろうと決めました。（地味に仕事がない、というかさぼりたい、という背景もありつつ…)

# ユーザーにとって、わかりやすくするには

多くの人に使ってもらえるにはどうしたらいいか。それが簡単にわかるのであれば誰でもやっていると思います。だから難しいわけですが、ひとつ確実だと思うのは、「わかりやすい」ということだと思います。目的がわかりやすいとか、UIがわかりやすいとかいった色々な意味でわかりやすということです。少し触っただけでわかりやすくないと、ユーザーはすぐに離れていってしまうと思います。

# ブラシ塗りを導入することにした

このツールで断トツでわかりづらかったのが塗りつぶしです。Canvas2Dのパス描画の仕様そのままで「囲んだ範囲が塗りつぶされる」なので、一般的なペイントソフトと全く操作感が違うのが問題でした。

![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59191/2df2d6ab-68d0-05a0-87b4-1757abcfc54b.gif)

「自動塗りつぶし」を作ったりもしたのですが、どうしても精度が出なかったので、素直に一般的なペイントソフトのようなブラシで塗る形を用意することにしました。ビットマップブラシを使えるようになれば、もっとマットな感じの絵も描けるようになるという期待もあります。

# ブラシ設定のUIを作った

ブラシ塗り導入のために、まずはブラシの設定をツールごとに持てるようにしました。そしてその設定を変更するためのUIを実装しました。
なんだか一気に見た目がペイントソフトっぽくなった気がします。こういうのは作っていて楽しいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59191/94b0143f-4854-770a-cdd6-297f6fdaeb5e.png)

# モバイルアプリにしたいと思ってUIの改善を試みた

ブラシ塗りとは別に、モバイルの画面の縦横比でも使えるようにデザインを調整してみました。

たとえば、タッチ操作のことを考えて画面上部のUIを中央寄せにしました。マウスではなく指での操作になるので、利き手に関係なく指が届きやすいようにと考えました。サイドバーなんかもそのうち左利き対応したいと思っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59191/2363647e-5a10-c141-a1f3-6be1d691d61d.png)
関係ないですが、Windows11のタスクバーが中央寄せになったときは同じ発想かと一瞬思いました。でもたぶん最近のタブレットの画面デザインに寄せたんでしょうね。

さらに、アプリとして人気が出そうなモダンな雰囲気にしたいと思い、ボタン類を単純な枠線をやめて影をつけてみたりしました。いつだったか、ふわっとした擦りガラスのようなデザインが今後流行るぞ、という噂をきいたので、それも試してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59191/6e2ef171-ef4d-5d82-5678-5af1fa6f6682.png)
でも飽きたらやめるかも。無駄に重くなりますし、トレンドの移り変わりも速いですし。

# キーボードショートカットのカスタマイズができるようにした

自分ひとりで使うだけならショートカットはソースコードをいじればいいので必要なかったわけですが、他人に使ってもらうには必要だと思い実装しました。作っても自分では使わないという、自分にとっては珍しいパターンの作業でした。でもこれも、なんだかツールっぽくなってきた気がして楽しかったですね。実装は簡単なほうでしたし。楽で楽しいのはいい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59191/28613a45-cf5e-15c1-82e8-059729efcc28.png)

# アニメーションのオニオンスキン機能を実装した

今年最大のダメ案件。今年こそアニメを作るぞと意気込んで作ったのですが、日常が色々とありすぎて機能を作っただけで終わってしまいました。しかも実装したあと色々大きな変更があったので、今でもちゃんと動くのか自信はない・・・と思ってさっき試してみたら案の定、動きませんでした。ゆえにスクリーンショット無し！ ごめんなさい。
なお、アニメーション関係の機能はアプリとしてリリースするときは無効にする予定です。バグの温床なので、バグ対応が追いつかないと思います。なにせ一人でやってますから。

# いまどきのビルド環境を試した

何カ月かごとに「TypeScript　ビルド　高速化」で検索したりするんですが、どうもESBuildがいいらしいぞと噂をきいて導入してみました。たしかに思わず笑いが込み上げてくるくらい速いですね。ただし型チェックをしてくれないので、忘れていたところに修正もれが残ってバグになったりします。変更の内容によって tsc --noEmit でチェックするようにしています。

また、その後、Viteも導入してもみました。内部的にESBuildを使っているらしいので速度は変わらないわけですが、ビルド環境を自前で改善し続ける手間を省きたかったというのがあります。しかしこういったものを導入するたびに設定ファイルの書き方を調べる必要があって面倒ですね。みんな同じならいいのに…。

# ファイル名の規則をハイフン区切りに変えた。

細かいことですが、今まではアンダースコア区切りでした。なぜそうだったのかは、はっきりとは記憶にありません。以前はともかく、今はnpmを前提にするかぎりハイフン区切りが主流な気がしますが…どうなんでしょうか。npmをのぞいてみると、今でもけっこう混沌としている気もします。TypeScriptなのでパスカルケースでもいいんですけど、自分は特にこだわりは無いので、長いものに巻かれてReactやAngularと同じハイフン区切りで行くことにしました。

# 「塗りつぶしレイヤー」を「囲み塗りレイヤー」に名称を変えた

前述の通り、囲んで塗る操作はあまり直感的とはいえません。顕著な例は下のような場合で、細かいところを小分けにして塗っていくと、囲んでいない部分が残ってしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59191/dd149619-93db-0f8b-b80e-094f4b832d98.png)
この残り方は直感に反するところがあると思いますし、絵が複雑になってくると後から修正しようがなくなっていきます。

ただ、囲み塗りにも良いところもあって、単純な形状（円とか）をベタ塗りするだけなら楽だったりしますので捨てがたいです。
そこで考えたのが、名前を変えてユーザーに「囲んで塗るんだ」という意識を持ってもらおうということです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59191/9936ac16-481d-39bf-aebb-bbf93b0889d5.png)
運用で回避みたいな発想ではありますが、意外と作っている側（筆者）も意識が変わりました。連続している箇所に補助線を表示するとか、これから描くところに向かって補助線を出したりするとかいったアイデアが出てきたので、捉え方しだいなんだなと思いました。

あと、内部構造を考えて操作しないとデータが壊れていく仕様（？）だったのを、改善しました。やはり自分で使うだけだと、そういうところを放置しがちですね。

# はみ出さない塗りの実装

ブラシ塗りをこのツールの主軸にしていこうとしているわけですが、ひとつ大きな問題がありました。それは「線をはみ出さないで塗る」が難しいということです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59191/17bad4ee-b7a0-c667-8679-7c2089e05ea9.png)
もちろん、ブラシの大きさを小さくして細かく塗っていけばはみ出さないで塗ることはできますが、非常に面倒臭く、かつ難しいです。
また、ドロー系なので、はみ出した部分を消しゴムで後から消すということができません。もしくは消しゴムデータが累積し続けるのでよければできるんですが、それはできれば避けたい。

それで色々と考え、実験もしました。詳細は今年のアドベントカレンダーに投稿していますので、ご参照ください。まあ四苦八苦でしたが（自分で言う）いちおう成果はあり、マスクを生成してはみ出す部分を削る形で実装にこぎつけました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59191/f693f0a6-c526-ea35-0a8a-54b080c10516.png)
（自作ツールで塗ってみている図。はみ出さないのは本当にラク）

１２月に入ってからツール本体に実装しはじめましたし、バッファリングとか複数レイヤーが連動するとか複雑ですし、バグが嵐ですし、泣きながら実装しました。いや泣いてはいなかったですが、[どら焼きの禁断症状に苦しむドラえもん](https://www.google.co.jp/search?q=%E3%83%89%E3%83%A9%E3%81%88%E3%82%82%E3%82%93+%E3%81%A9%E3%82%89%E7%84%BC%E3%81%8D+%E7%A6%81%E6%96%AD%E7%97%87%E7%8A%B6&source=lnms&tbm=isch&sa=X)のごとく、うめきながらやってましたね。日常茶飯事なんですけどね。

# 感想、今後

いやー、はみ出さないブラシ塗り（の基礎）ができたのは、悩んだかいがあったと思います。とにかく動いたので現状は満足です。

今後ですが、線を引いたり修正したりするツールはこのソフトの目玉なので、それを洗練したいと思っています。また、普通のお絵描きツールにあるはずの機能が足りていないところがあるので、それもやります。たとえばブラシにクレヨンと水彩を足したいですし、ファイル一覧のサムネイル表示もしたいです。

そして、どうしたら使ってもらえるようになるか、独自の便利な機能があるのをどうやってユーザーに伝えるかも考えていきたいです。自信をもってユーザーに使ってもらえる状態にしたいと思います。あと、どうやってマネタイズするかですね。うーんわからん。

# おわりに

ということで、Webグラフィックスアドベントカレンダー最終日でした。

この一年、アドベントカレンダーで発表することを目標にやってきました。この時期以外ほとんど情報発信をしませんが、やはり目標があると一年が積極的になって楽しいです。特に年末になると積極的(笑)。そして来年も目標に向かって頑張るぞという気持ちになります。

参加した皆さま、記事を見てくださった皆さまに感謝いたします。
できれば来年もまたお会いしましょう。
皆さまどうか良いお年を・・・。