ずっと黙っていようと思っていたんですが、誰も聞いてくれないので告白します。
近いうちに破滅派からePub長編小説を出版すべく、ISBNを取ったり、ePubの作り方を調べたりしています。
明日には原稿の校正を終え、あとはePubファイルを作るだけという状況です。
Appleに無視されてるテキスト両端揃え
さて、今回のネタはAppleスタンダードから無視されている日本語Web組版の一助となるような内容のはず。すでに誰かがやっていた場合は無視してください。
HTML5+CSS3日本代表(?)である村上真雄さんが書いている通り、「SafariやChromeの元になっているWebkitではtext-align:jutifyが効かないので、両端揃えができない」のですが、これは電子書籍問題としてとてもまずいです。
というわけで、今回はJavascriptを用いて強引にそれっぽくしてみました。詳しくは写真をどうぞ。
基本的なアイデアとしては、以下の通りです。
- Webkitでtext-align:justifyを指定することはできるが、text-jutifyプロパティがないので、半角スペースの部分でしか字間を調整してくれない。
- 日本語は基本的に半角スペースによる分かち書きをしない(してる人も少しいる)ので、Webkitが半角スペース(inter-word)以外でも字間を調整してくれようになるのを待つしかない。
- それは嫌なので、とりあえずすべての字間に幅0の半角スペースを突っ込みまくって調整させればよくない?
ということです。Javascriptで実装したのは、Webkitがtext-justifyプロパティに対応した場合、すぐ外せるからです。getComputedStyleメソッドとかでプロパティの有無を調べてから実行する形式にするともっといいかもしれません。
ソースはこんな感じです。
css
.kusabi{ width:0; font-size:0; overflow:hidden; }
Javascript(MooTools利用)
window.addEvent("domready", function(e){ //字間を調整しない文字のリスト。要更新。 var list = /[a-zA-Z0-9/「」〈〉《》¥[]〔〕,.""ヶッゞ。、・ー]/; //時間調整用のspanタグ。半角スペースのみを含む。 var s = "<span class=\"kusabi\"> </span>"; //対象となるpタグに対して反復処理。 //ここではpタグが含むテキストに対して処理を行っているが、 //本来はテキストノードに対して処理を行うべき。 //xPathとか使うと吉かも。 $$("#content p").each(function(elt, index){ var text = elt.get("text"); var newText = ""; var textArr = text.split(""); textArr.each(function(t, i){ //ここのアルゴリズムは適当。 if( textArr[i + 1] && !t.match(list) && !textArr[i + 1].match(list) ){ newText += t + s; }else newText += t; }); elt.set("html", newText); }); });
ポリシーとしては今のところこんな感じです。
- 句読点、拗音、発音、促音の前にはスペースを入れない
- 半角英数の単語の間にはスペースを入れない
ちょっとやってみたところ、まあいい感じなのですが、最後にわずかなスペースが入ってしまうのと、やはりスペースのサイズが完全に0にはならないので、妙に文字間が間延びしていることでしょうか。
文字サイズが大きい場合はそれほど気になりませんが、文字サイズを小さくするとやけに目立ちます。
とはいえ、Webkit限定ということを考えれば、色々と工夫の余地はあると思いますので、今後も引き続き検証してく予定です。乞うご期待。
一応、現時点でのソースをgistに上げておきます。iPhoneで見てる人はデモで確認してみてください。
追記@2010-09-16
実機に転送してみたところで次の問題発生。
- iPhoneのJavascript実行時間は10秒だったはずなので、forループでスタック。TimerEventに変更してトライ→SafariではOK。
- 星海社のサービスからCSSをパクってRubyを実現。inline-tableを使えばいいらしい。
というわけで、ちょっとずつ問題を解決していきましたが、どうしても解決できなかったのがiBooksでの検証。
iBooksでは一応Javascriptを実行できるはずなのですが、appendChildとかで要素を追加すると、レンダリングがぶっ壊れるみたいです。
今回修正したアルゴリズムでは、setIntervalに応じてジャスティフィケーションをほどこした文字を一個ずつ追加していくというものだったのですが、2ページ名以降がなぜか表示されないんですね。
で、色々試行錯誤した結果、Javascriptによる処理を終えた後(これが結構時間かかる)に画面をローテーションさせると2ページ目以降も読めるようになるんですが… ページの一番下にあるページネーターが表示されなくなるんですね…
これは単なる予測にすぎませんが、Mobile Safariの描画エンジンとiBooksの描画エンジンでは、描画のタイミングがちょっと違うっぽいですね。
Webkit(というか、普通のブラウザ)はJavascriptでなんかやるたびに描画されますが、iBooksはそうではないようです。
パッと見た感じ、通常のDOMの上にもう一個ラッパーみたいなのをかぶせてから制御しているんじゃないでしょうか。
というわけで、結局iBooksでJustificationには挫折した訳ですが、今回やってみて気づいたことが一つ。
iBooksやiPhoneアプリはやはりAppleのためのエコシステムという感じがします。
この軛から逃れるには、Webの世界に逃れていく(つまり、Mobile Safariだけをターゲットにする)という選択肢しかないような気がします。
iBooksの魅力は「ビューアー作らなくていい」と「決済システムいらない」の2点に尽きるわけですが、現状のMobile SafariとiBooksの差を見ていると、iBooksサイコー!って言いづらいですね。
というわけで、愚痴でした。