2024年1月6日土曜日

アイコン点つなぎを作った

アイコン点つなぎ を作りました。



幼児教育では点つなぎやグリッド点つなぎが有名です。 それらは線を書く練習や、簡易的に認識力を向上させる練習として便利ですが、題材を作ったり探すのが大変です。 そこで自動生成してゲーム化すると面白そうだなと思って作りました。

難しいところ

とはいえ一般的な点つなぎを作るのはなかなか難しいです。一番の問題として、点つなぎは点が重複しない特徴がありますが、アイコンはかなりの確率で点の位置が重なります。 他にも SVG は図形が重なる問題が大きいです。 これらの問題を解決するために、すべての数字を表示するのは諦めて path ごとに数字を表示して、ちょっとずつ絵を作るゲームにすることで回避しました。 点つなぎだけでなく SVG の勉強にもなります。 この回避策を入れても重なるケースはままあるので、点を近傍領域へ再配置するようにしてみたところ、まあまあいい感じに動きました。

作り方

path 以外の図形をどうするか、という問題が気になった人もいるかも知れませんが、Web 上ですべての SVG 描画要素を path に変換しています。 これは使いやすいライブラリがなかったので自作しました。 あとは点をつなぐためのの数字の表示ですが、まず svgpath を使って配列の座標にします。 path 配列から text で数字を表示します。 あとは text を順番にタッチしたときに path の線を復元するようなコードを書けば完成です。

ただ実際には SVG の様々な表示形式のサポートが必要です。 たとえば transform の復元、use タグの復元、それに伴った CSS の復元、style 属性の調整、currentColor の調整などなどを行う必要がありますが、なんとかします。 さらに真面目に処理する場合、style タグの解析、animate タグの解析が必要ですが、面倒なので今は使っていないアイコンに限定しました。 もっとも style タグが影響があるのは Arcticons と Carbon Icon くらい、animate タグは Material Line Icons くらいでしょうか。 また数字の表示位置は元の SVG の表示領域を突き抜ける可能性があるので調整が必要です。 そのような細かな処理をきちんと加えていけば、どんな SVG でも動く点つなぎが出来上がります。

アイコンにも色々ある

アイコンをたくさんサポートするのは容量的にも作業的にも大変なので、軽量で有名で使いやすく、多くのアイコンを含むセットだけをサポートすることにしています。 このチェックが意外と面倒で、たとえば Phosphor Icons はアイコンの種類は 1200 ほどで、形状が異なるものが 6種類あります。 形状に関しては、多くのアイコンセットではたいてい fill か outline かぐらいの違いしかないので、すべてサポートするのはあまり意味がありません。 fill なら外枠だけ書けば良いので楽、outline は内枠も必要ですこし難しいとは思う一方で、 黒字を内抜きするような場合は同じ手間が掛かる可能性があるので、細かな分類は大変そうです。 両方サポートすることにしました。 他には sharp, round, bold などの違いがありますが、これは本当に差がないので、一番ファイルサイズが小さくてシンプルなものにしました。 この基準でサポートしているのは、Material Icons、Material Design Icons、Phosphor Icons、Tabler Icons、Bootstrap Icons、Remix Icon の 6つです。

アイコンセットによっては、稀に外枠と内枠を一つの線で書いているもの (Line Icon?) があります。 これが世の中の点つなぎに一番近いもので重要と考えています。 ただそのような書き方をしているアイコンセットは多くありません。 また地道にソースコードを見る以外で見分けが付かないので確認が大変です。 今のところ Line Icon として使えて数が多いものは Iconoir、Solar icon set、Majesticons、Lucide くらいと思っています。 これらは優先的にサポートしました。 Material Line Icons も使えそうでしたが、animateMotion タグの解析が大変そうだったので見送りました。

今のところ 3万個くらいのアイコンをサポートしています。 少し変わった点つなぎと考えても良いですし、IT デザインの仕組みを知るのにも良さそうです。 アイコンだとあっさりした問題が多いので、他にもいくつか似たようなものを作ってみています。

0 件のコメント: