2024年1月16日火曜日

漢字点つなぎを作った

漢字点つなぎを作りました。 書き順は考慮する必要がないのでいい感じのフォントさえあれば作れます。 とはいえそこがハードルで、思ったより考えることがありました。



フォント選び

まず教育用途のアプリでは漢字のフォントをどうするか問題があります。 教育用途では教科書体が使われるのですが、いまだに教科書体の無料フォントはありません。 ただ最近クレーOne というのが出てきて、多少の課題はありますが教科書体として使えそうだったので使ってみました。 しかし点つなぎで遊ぶには点の数がちょっと多過ぎると感じました。 フォントはアイコンや絵文字と違ってシンプルさを求めているとは限らないですからね。 今回は綺麗さよりシンプルさのほうが大事とわかったので、Noto Serif JP を使うことにしました。 中学以降は教科書体ではなく明朝体が使われるので、 その書き方に慣れるくらいの意味合いで遊べば、まあ問題はないでしょう。

Noto Serif JP 以外に良いフォントがないか、改めて色々なフォントを見ました。 シンプルで良いなあと思うのはゴシック形式の Noto Sans JP で、これはサポートしておきました。 ただ Noto 以外で点つなぎに使えそうなもの、と考えるとなかなかちょうど良いものはない気がしています。

ttf2svg

フォントから SVG への変換は @marmooo/ttf2svg を使っていますが、 細かな調整が必要になったので、ついでに改良しておきました。 具体的には、文字を仕様上表示され得る領域にSVG化するのと、 ぴったり拡大して最大領域に SVG 化するのは微妙に違い、 対応しにくい問題があったので、細かな調整ができるようにしました。

たいていの絵文字やフォントは advancedWidth と linespace = ascent - descent + linegap を見れば、SVG の viewport を決定できます。 ただ漢字にこの条件を当てはめると、特に descent の影響が大きすぎて不自然な余白が生まれます。 とはいえ descent だけを無視する訳にもいきません。 なぜならフォントの作者によって、ascent, descent はバラバラの意味を持っているからです。 そこで units-per-em を使うと、ぴったりになることが多いです。 ただ units-per-em も壊れたデータが入力されていたり、縦横比が壊れていると意味をなさなかったりします。 仕方ないのでオプションで数字調整できるようにしました。

しかしこれでも点つなぎで遊ぶには調整が不足しています。 具体的には、(1) ローマ字でさえ x 座標がマイナスになることがあり、SVG 化で表示が崩れる危険性があります。 (2) また表示するテキスト自体がない文字も多数あるので、細かな除外が必要です。 TTF を SVG 化するのは、細かいところを見始めると思っていたより難しいんだなと思いました。 getBoundingBox() でぴったりのサイズにするのも一つの手ですが、縦横比が崩れるので一長一短です。 これらの問題をチマチマ対処するのは面倒で、JIS 第 4 水準までの漢字に限定するのが楽そうです。 その場合は縦横がシンプルな固定領域で表現されるので、悩む必要がありません。

そんな訳でサポートしているのは約 1万1000種類×2=2万2000個のグリフです。 これだけあれば量で困ることはないでしょう。 アイコン点つなぎと違ってそれなりに歯ごたえがあります。

0 件のコメント: