8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Quad incAdvent Calendar 2015

Day 21

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

Last updated at Posted at 2015-12-21

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の横幅を取得できません。ご注意ください。

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

8
8
0

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
  3. You can use dark theme
What you can do with signing up
8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?