LoginSignup
8

More than 5 years have passed since last update.

posted at

updated at

Organization

JSでカーニングエンジンを作ってみる 2回目

Fallout4面白いですね。日本語の行間とか最悪ですね。読みづらすぎますね。
前回はとりあえず実現可能性を探っていましたが、今回は本格的に機能を検討したいとお思います。

カーニングデータを分離

エンジン部分とデータを分離しておいた方が、Fontごとにデータを作ることができて便利ですよね。JSONも良いですが、今回は別のJSファイルに記述します。

実際に使う場合はconcatしても良いと思います。今回はヒラギノフォント用で進めます。
JSファイル名を「PIPKerningHiragino.js」としてます。

JSのクラス名は「PIPKergninTable」、これはすべてのフォントで同じです。ファイル名で識別します。

PIPKerningHiragino.js
(function(global){
    "use strict";

    // モジュール設定
    global["pipboy"] = global.pipboy || {};
    var module = global.pipboy;

    module.PIPKerningTable = function(){

    };

})((this || 0).self || global);

行頭データを追加する

まずは行頭ぞろえ用のデータを検討します。

"「"
"("

は文字の半分だけ内側に入ってしまいます。これ毎回きになりますよね。CSSではネガティブマージンで調整することができます。

クラス変数にマージンの値をもたせます。

PIPKerningHiragino.js
// Beginning of Line (行頭)
module.PIPKerningTable.BOL = {
    '': '-0.5',
    '': '-0.5'
}

これで行頭ぞろえの準備はできたので、一旦エンジン側に移ります。行頭以外のカーニングは、エンジンの基本的な実装ができてから再度設定します。

カーニングエンジンの設計

カーニングを適用する方法はシンプルにCSSのクラス設定のみにします。
カーニング指定するDOMに「pip-kerning」クラスを指定してください。あとは自動的に設定されると便利ですね。

<h1 class="pip-kerning">「見出し1」です。classにpip-kerningを設定</h1>

自動的に実装するので、

  • DOM要素を抽出
  • spanタグで一文字づつ囲みカーニング設定
  • 行頭設定

の順番で検討してみます。

PIPKerningクラスを作る

カーニングエンジンJSを作ります。「PIPKerning.js」とします。クラス名も「PIPKerning」です。

module.PIPKerning = function(){
    // プロパティなど
};

まずは「pip-kerning」でDOM要素を抽出します。

var $elements = document.getElementsByClassName('pip-kerning');

これでHTML上のすべての要素を取得しました。$elementsは配列です。
各要素をそれぞれ処理します。

var $elements = document.getElementsByClassName('pip-kerning');
var len = $elements.length;
for(var i = 0; i < len; ++i){
     var str     = $elements[i].innerHTML;
     var newHTML = this.__define(str); // __defineはプライベートメソッド
     $elements[i].innerHTML = newHTML;
}

innerHTMLでテキストを抜き出し、this.defineでspanタグ実装します。最後に新しいhtmlを追加します。
次にdefineの実装をします。
処理部分を抜き出すのこんな感じです。文字をバラバラにしてspanで囲むだけです。カーニング設定はまだです。
ただし、インラインスタイルで「inline-block」を必ず指定してください。これは行頭ぞろえで使います。

PIPKerning.js
var characters = str.split('');
var table = module.PIPKerningTable.table;
var len = characters.length;
var output = "";
for(var i = 0; i < len; ++i){
    output += '<span style="display: inline-block;">' + characters[i] + '</span>';
}
return output;

行頭ぞろえ

次に行頭ぞろえの処理を実装します。行頭はウィンドウサイズで変わる可能性があります。(デバイスサイズ依存)
これは面倒くさいですね。
今回はカーニング領域のサイズを取得し、各文字のサイズと領域のサイズを比較し行頭を見つけます。

PIPKerning.js
// 行頭処理
var $childs = $elements[i].getElementsByTagName("span"); // 各文字(1文字)
var rowWidth = $elements[i].clientWidth;
var currentRowWidth = 0; // 行
for(var j = 0; j < $childs.length; ++j){
   currentRowWidth += $childs[j].clientWidth; // 行の横幅を加算していく。文字数が増えれば大きくなる
   if(currentRowWidth >= rowWidth || j == 0) { // 行の幅と、最初の一文字目を行頭と判定
       var bol = PIPKerningTable.BOL[$childs[j].innerHTML] + 'em';
       if(bol) {
           $childs[j].style.marginLeft = bol;
           trace($childs[j].style.marginLeft)
       }
       currentRowWidth = 0;
   }
}

行の横幅はclientWidthで取得し、forループの中で各文字のサイズを調べます。inline-block設定がないと、spanの横幅を取得できません。ご注意ください。

これで行頭ぞろえが実現できました! 
ブラウザのリサイズは上の処理を再度実行すればできますね。その辺は次回に...
今回はここまでです。つぎは本題の文字ごとのカーニング実装です。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
8