スター・ウォーズ風の自己紹介を、マス目に並べる
奥へ流れる自己紹介の文字を、映画のフレームと同じく1行きっちり同じ文字数にそろえた。禁則なし・両端そろえ・全角化と、ファイルに存在しない空白の話。
#CSS#文字組み#3D変形
このサイトの自己紹介は、映画『スター・ウォーズ』のオープニングのように、黄色い文字が画面の奥へ傾いて流れていく演出にしています。文字は奥へ行くほど小さくなり、やがて消える。そして、文字を最後まで読み終えると、カメラが惑星へ戻っていきます。
これは Three.js ではなく、HTML と CSS の 3D 変形だけで作っています。見た目の寸法は、実際の映画のフレーム(参考画像)を測って合わせてきました。この回は、その「文字の並び」を参考画像に合わせた話です。
寸法は合わせたのに、文字組みは合わせていなかった
8月の初め、こう聞きました。
自己紹介文の文字一つ一つの配置について、参考画像のように、きれいに一列にする方法はありますか?
参考画像の文字は、縦にも横にもきっちりそろっています。まるで原稿用紙のマス目に1文字ずつ置いたようです。一方、このサイトの文字は、真ん中寄せでブラウザ任せに折り返していたので、左右の端がギザギザでした。
振り返ると、文字の大きさや傾きの角度は何度も参考画像に合わせてきたのに、文字の組み方だけは一度も参考画像に照らしていなかったのです。
参考画像から読み取れた4つのこと
改めて参考画像を読み直すと、4つのことが分かりました。
- 1行きっちり13文字。 「反乱軍の苦闘は続いていた。」「恐るべき帝国宇宙艦隊の追撃」、どの行も13文字です
- 左右の端がそろっている。 段落の最後の行だけが短い
- 禁則処理をしていない。 「ォーカーに率いられた自由の」のように、小さい「ォ」が行の頭に来ている
- 段落の1行目だけ、1文字下げている
面白いのは、3つ目が1つ目の原因になっていたことです。普通の日本語の組版では、小さい「ォ」や句読点が行の頭に来ないように、前の行に追い出したり引っ込めたりします(禁則処理)。でもそれをすると、その行だけ12文字や14文字になって、マス目が崩れます。参考画像は、小さいカナを行の頭に置いてまで、13文字を守っていたのです。これに気づかないと、1行13文字は再現できません。
幅を「文字数」で決める
1行の文字数を決める方法は、意外とシンプルでした。CSS の em という単位は、「その要素の文字の大きさ1つぶん」を表します。そこで、文字の大きさと同じ要素に「幅=15em」を指定すると、幅がちょうど全角15文字ぶんになります。画面の大きさがどう変わっても、1行の文字数は変わりません。
最初は参考画像と同じ13文字にしましたが、その後、15文字に変えてもらいました。参考画像から学んだのは「全部の行が同じ文字数で、両端がそろい、禁則が無い」という組み方であって、13という数そのものではないからです。ここを混同すると、あとで誰かが「参考画像に合わせる」と言って13文字に戻してしまいかねないので、その理由もコードのコメントに書いてあります。
それまでは、画面の大きさに応じて文字の大きさを4段階に切り替えていました。これも「1行の文字数をだいたい保つ」ための工夫でしたが、実際に測ると、1行の文字数は 9.7、14.6、13.8、15.0 文字とばらばらでした。幅を文字数で決めた今は、段階を持つ理由がなくなりました。
両端そろえ、禁則なし、1字下げ
組み方の3点は、CSS で次のように指定しています。
- 両端そろえ(
text-align: justify) - 禁則なし(
line-break: anywhere) - 段落の頭を1文字下げる(
text-indent: 1em)
1字下げは、ちょうど1マスぶんなので、下げてもマス目は崩れません。
ここで1つ気になったのが、真ん中寄せをやめることでした。この演出は、文字の列を奥に向かって傾けています。コードには「左寄せにすると、行が遠近の中心から外れてゆがむ」という注意書きがありました。でも考えてみると、両端をそろえた行は、全部の行がちょうど同じ幅なので、真ん中寄せと同じくどの行の中心も遠近の中心に乗ります。問題になるのは行の中心がずれることで、行の頭の位置ではありませんでした。
半角の英数字が、マス目を静かに崩す
文字組みを変えて、もう1つ決めることがありました。自己紹介には「Miiiwa」「2019年」「42tokyo」のような英数字が16か所ありました。半角の英数字は、全角の半分くらいの幅しかないので、混ざるとその行だけマス目からずれます。
選択肢は、英数字を全角(Miiiwa)にしてマス目に乗せるか、半角のままブランド名の見た目を保つか、の2つです。僕は全角を選びました。
ただ、全角にしても、ブラウザが勝手に隙間を入れることがあります。最近のブラウザは、日本語と英字のあいだに少しだけ隙間を空けたり、括弧を半分に詰めたりする機能を持っていて、その初期値もまだ変わっている最中です。これを明示的に切っておかないと、表示は壊れていないのに、マス目だけが静かに崩れます。
ファイルに存在しない空白
実際に1行ずつ測ってみると、1か所だけ、行が半マスずれていました。原因は、原稿の書き方でした。
1段落目の文章を、コードの中で2行に折り返して書いていたのです。React(JSX)は、文章の途中の改行を、半角の空白1つに置き換えます。そのせいで、「です。」と「「面白い」のあいだに、ファイルのどこにも書いていない空白が1つ入っていました。原稿を検索しても出てこないし、症状は「60行中1行が半マスずれる」だけ。段落を1行に書き直して直しました。
半角の混入も、この見えない空白も、表示が壊れないまま格子だけが崩れる種類の不具合です。こういう「黙って崩れる」ものは、あとで誰かがうっかり戻しても気づけるように、テストで見張ることにしました。自己紹介の原稿のファイルを文字として読み、「半角の英数字が混ざっていない」「1つの段落が2行に折れていない」を確かめています。
斜めの文字は、斜めのまま測らない
最後に、測り方で1つつまずきました。
画面に表示された文字の位置をそのまま読んで行を組み立てたら、「25文字の行がある」という結果が出ました。当時は1行13文字のはずなのに、です。原因は遠近法でした。奥の行は小さくなって、上下の位置がほとんど重なるので、2行が1行として数えられていたのです。
測るあいだだけ傾きを外して、平らな状態で測り直すと、4つの画面幅すべてで、全部の行がきっちり同じ文字数で、右端が1ピクセル未満の誤差でそろっていました。投影がからむものを画面の座標で測るときは、まず投影を外して同じものを測る。 これも、このプロジェクトの測り方の決まりに加わりました。
映画のオープニングの文字は、何気なく流れているようで、実はきっちり組まれていました。自己紹介を読むときは、ぜひ文字が縦にそろっているところも見てみてください。
