「transitionプロパティ」で設定したアニメーションでは、アニメーションの終了をJavaScriptのイベントとして取得することができます。

アニメーションイベントを利用することで、ちょっと複雑なアニメーションを作成することができます。

transition終了を検知

サンプルを見る

このサンプルでは、2カラム構成のボックスを2段階のtransitionで表示します。Flashコンテンツなどで、こういった展開をするサイトをよく見かけますね。transitionプロパティと終了イベントをうまく利用することで、簡単にこういった処理を行えます。

※今回も、CSS3の「transitionプロパティ」に対応した「Firefox」「Chrome」「Safari」でしか動作しません。 残念ながら現時点ではIEは「transitionプロパティ」には対応していません。

では早速記述を見てみます。

<style>
#wrap
{
    width:80px;
    height:80px;
    background:#CCC;
    color:#FFFFFF;
    overflow:hidden;
    transition:height 200ms ease-out;
}

#box
{
    width:400px;
    height:600px;
}

#box2
{
    float:right;
    width:300px;
    height:600px;
    background:#000;
}

#box p
{
    font-size:12px;
    cursor:pointer;
    margin-top:25px;
    margin-left:10px;
    padding:5px;
    float:left;
    background:#666;
}
</style>

</head>
<body>
<div id="wrap">
    <div id="box">
        <p>クリック</p>
        <div id="box2"></div>
    </div>
</div>
</body>

「#box」を固定幅にして、その中に「p」と「#box2」をFloatで配置します。 そして、それら全体を覆う「#wrap」を用意し、「overflow:hidden;」を設定。この「#wrap」の幅と高さを変更することで、コンテンツ全体の表示・非表示を切り替えられます。

図にすると下のようになります。

ではJavaScriptの記述を見てみましょう。

<script>
var callBack;

$(function ()
{
    $("#wrap p").toggle(
        function()
        {
            $("#wrap").css("height", "600px");

            callBack = function()
            {
                $("#wrap").css("transition", "width 200ms ease-out");
                $("#wrap").css("width", "400px");
            }
        },
        function()
        {
            $("#wrap").css("width", "80px");

            callBack = function()
            {
                $("#wrap").css("transition", "height 200ms ease-out");
                $("#wrap").css("height", "80px");
            }
        }
    );

    $("#wrap").bind("webkitTransitionEnd" , function(e){callBack();});
    $("#wrap").bind("transitionend" , function(e){callBack();});
});
</script>

transitionプロパティのアニメーションの終了を検知するコードは下記2行です。 「#wrap」に、transition終了イベントを、jQueryの「bindメソッド」を使ってイベントハンドラを指定します。

$("#wrap").bind("webkitTransitionEnd" , function(e){callBack();});
$("#wrap").bind("transitionend" , function(e){callBack();});

ChromeやSafari、iPhone、AndroidなどのWebkit系では「webkitTransitionEnd」、Firefoxでは「transitionend」という名前のイベントが発生します。 ここでもベンダープリフィックスのような感じで名前が違ってたりしますが、イベント名に関しては「prefixfree」も対応していません。 まぁ、存在しないイベントに関しては無視されるので、両方書いても大したコード量ではないので、ここは我慢しましょう(笑)

あとは前回おなじみの「toggleメソッド」で、開く・閉じるを実装します。

考え方としては、
開くとき:「heightを600pxに変更」 → transition終了のイベントハンドラ内で「transitionプロパティをwidthに変更」 → widthを400pxに変更
閉じるとき:「widthを80pxに変更」 → transition終了のイベントハンドラ内で「transitionプロパティをheightに変更」 → heightを80pxに変更
という処理を交互に行います。

その際、toggle内で

callBack = function()
{
    $("#wrap").css("transition", "height 200ms ease-out");
    $("#wrap").css("height", "80px");
}

この様に「callBack」を毎回書き換えることで、イベントハンドラを交互に切り替える処理を実現しています。

このサンプルはあまり派手なことはしてませんが、transitionを工夫すれば、下記のようなアニメーションも簡単に実装できてしまいます。

サンプルを見る

transition終了イベントの落とし穴

この様に一見簡単そうに見えるtransition終了イベントの取得ですが、始めてtransitionを弄るときに陥りやすい落とし穴があります。 百聞は一見にしかず、サンプルを見てみてください。 このサンプルでは、「transitionプロパティ」に「all」を指定し、幅・高さのtransitionの実行を交互にではなく、 同時に実行しています。

サンプルを見る

イベント終了時に、「OPEN」「CLOSE」とアラートするだけのプログラムですが、なぜか2回アラートされますね。 これはtransitionしているプロパティが2つあるためで、transitionの終了イベントは、transitionしているプロパティの分発生します。

なので、transitionの終了を検知して、処理を繋げたい場合は、transitionするプロパティを一つにするか、変数をカウントして、一回だけ処理されるような工夫を入れるのが良いでしょう。

河野 義貴
インハウスのFlashクリエイターとして勤務後、2010年独立。一年間のフリーランス期間を経て、2011年9月にスウィーツアンドストリーム株式会社を設立。主にFlash・HTML5を駆使した、PC・スマートフォン向けインタラクティブコンテンツを中心に活動中。マイナビクリエイターセミナー(WCBセミナー)の講師としてもおなじみ。

クリエイター向け転職・派遣情報サイト「マイナビクリエイター」より転載