みなさま、あけましておめでとうございます。@tsmallfieldです。
本年もこの_level0をよろしくお願いいたします!

さて、2012第一弾はお正月のスペシャルコンテンツ「おHTML5」!!
制作にあたっての技術的な裏話をご紹介します。


おHTML5

ohtml5_img_1.jpg

「おHTML5」はブラウザの様々な機能を利用した、くすっと笑える遊び心120%のスペシャルサイト。
<select>や<input>といったいつも見慣れた部品であんなことやこんなことまで!!

まだ未チェックの方は今すぐこちらのURLへ!
http://ohtml5.kayac.com/

実装体制

フロントの実装は私とイタニティーの2人で行い、主にフレームワークを作成する側とそれを使用する側という役割分担としました。

専用ライブラリ barbie.js

今回は実験的コンテンツということで、jQueryといったフリーのライブラリを一切使用していません。

「えっ、ライブラリなしとか絶対無理。。。。」と思ったそこのあなた!! 安心してください。

なぜなら本サイトの対象ブラウザはChromeのみ!
querySelector()やclassListといった、今まで使いたくても使えなかった便利で魅力的な新機能を思う存分使えるのです。

今回「おHTML5」のため作成した専用ライブラリがその名も"barbie.js"!
JSの読み込み機能からウィンドウのアニメーション制御までを可能にする即席ライブラリです。
ちなみにバービー(barbie)とは担当ディレクターばびこの愛称。
こういう遊び心、大事ですよね!

ポップアップウィンドウの制御

ohtml5_img_2.jpg

ではさっそく技術的な話題に入りましょう。

今回のテーマの一つが、ポップアップウィンドウの制御。
window.open();で生成したウィンドウの座標、位置をアニメーションで変更したり、
複数のウィンドウ間の連携機能を実装する必要があります。
これらの機能は「初夢の窓」や「スクロールやぶさめ」、「ブラウザ凧揚げ」でガッツリ使われています。

AnimatablePopup

"AnimatablePopup"はウィンドウオブジェクトをラップするクラス。
座標/位置のアニメーション機能、ウィンドウ間の通信機能を備えています。

クラスの使用方法は普段通り。
new 演算子を用いてインスタンスを生成します。

var popup = new AnimatablePopup("hoge.html");

(それにしてもセンスのない名前。。。)


第二引数で様々なオプションも指定できます。

var popup = new AnimatablePopup("hoge.html", {
    innerWidth  : 200,
    innerHeight : 300,
    x           : 0,
    y           : 0,
    reuse       : true
});

座標、サイズのアニメーション

任意の位置(x, y)にアニメーションしながら移動するには以下のように指定します。

popup.moveAnimTo(x, y);

簡単ですね。

内部の実装はタイマーで定期的に座標を変更するという昔ながらの方法です。
なお、パフォーマンスを考慮し、一つのタイマーを全インスタンスで共有するようにしています。

イージングの指定

第2引数でイージングの種類も指定できます。

popup.moveAnimTo(x, y, TransitionType.EASE_OUT);

イージングのタイプは以下の4種類。

TransitionType.LINEAR;
TransitionType.EASE_IN;
TransitionType.EASE_OUT;
TransitionType.EASE_IN_OUT;

これらの中身はただの関数です。

いずれも指定された長さの、0から始まり1で終わる配列を生成し返します。
もし他の動きを望む場合はイージング関数を自前で用意しても良いでしょう。

popup.moveAnimTo(x, y, myEasingFunction);

function myEasingFunction(len) {
    // your code goes here;
}

参考までにTransitionType.LINEARの実装は以下のようになっています。

/**
 *  @param  {uint} n
 *  @return {Array.<Number>}
 */
function LINEAR(n) {
    var i   = 0,
        x   = 0,
        dx  = 1 / n,
        ret = [];
    
    for (; i < n; ++i) {
        ret[i] = x;
        x += dx;
    }
    ret[n - 1] = 1;
    
    return ret;
}

アニメーション時間の指定

アニメーションにかかる時間を[ms]で指定できます。

popup.moveAnimTo(x, y, TransitionType.EASE_OUT, 3000);

リピート&逆再生

ohtml5_img_3.jpg

「スクロールやぶさめ」では弓のウィンドウを左右に繰り返し動かす必要があったため、
第5引数でリピート指定ができるようにしました。

popup.moveAnimTo(x, y, TransitionType.EASE_OUT, 3000, TransitionOption.REPEAT);

だんだん引数が増えてきましたね。。。
そろそろ破たんしそうです。

ではアニメーション後、逆再生したい場合は。。。

popup.moveAnimTo(
    x,
    y,
    TransitionType.EASE_OUT,
    3000,
    TransitionOption.REPEAT | TransitionOption.AUTO_REVERSE
);

さすがにこれ以上引数が増えると怒られそうなので OR で指定するようにしてみました。
(これは最近Objective-Cをさわりはじめた影響です。。。)

参考までに、TransitionOptionの定義部分は以下のようになっています。

var TransitionOption = {
    REPEAT       : 1 << 0,
    AUTO_REVERSE : 1 << 1,
    .
    .
    .
};

取り出す場合は>>(右シフト)して&1すればOKですね。

オプションの指定方法に関しては、今考えると以下のようにした方がよかったかも。。。

var options = new AnimationOptions;

options.repeat      = true;
options.autoReverse = true;
options.duration    = 3000;
options.easing      = TransitionType.EASE_OUT;

popup.moveAnimTo(x, y, options);

もしくは。。。

popup.moveAnimTo(x, y, {
    repeat      : true,
    autoReverse : true,
    duration    : 3000,
    easing      : TransitionType.EASE_OUT
});

中~大規模案件ではこの辺の設計が重要になってきます。
あとで困らないように、きちんと設計しましょう。

最後に

さて、今回の記事いかがでしたでしょうか?
次回はカスタムイベント周りについて解説したいと思います。

HTML5飯