Mach3.laBlog

スクロールに応じたアニメーションにイージング関数を適用したい

この記事は賞味期限切れです。(更新から1年が経過しています)

縦長にスクロールしてアニメーションを楽しませるサイトも今では珍しくなくなってきました。 実装する機会もぼちぼちありそうなので、今日はそういったアニメーションでイージング関数を利用するお話です。

スクロールに応じたアニメーションにイージング関数を適用したい

スクロールに応じたアニメーションって何

「パララックス」と一言にいってしまえば良いのですが、 視差効果で立体的に見せる手法を指して「パララックス」と言うのならば そうではないコンテンツも多くあると思いますので、 「スクロール量に応じてコンテンツをアニメーションさせる事」を、 ここではそのように呼称したいと思います。

ちょっと長いので「スクロールアニメーション」でいいでしょうか。

シンプルな例

具体的にどういう事なのかをごくシンプルなコードで表現してみます。

$(window).on("scroll", function(){
    var scroll = $(window).scrollTop();
    $(".box").css({
        "top": scroll,
        "left": scroll * 2
    });
});

“.box” のtop/leftを現在のスクロール量に合わせて変化させる処理をスクロールイベントに登録しています。 位置の他にも、要素のサイズや色、スプライトされた背景画像のポジションなどを変化させれば ユーザーのスクロールにあわせて多彩な表現が出来ますね。

requestAnimationFrameを使ってみる

ここでスクロールイベントの代わりに、新しめの実装の requestAnimationFrame を使ってみようと思います。

var step = function(){
    var scroll = $(window).scrollTop();
    $(".box").css({
        "top": scroll,
        "left": scroll * 2
    });
    requestAnimationFrame(step);
};
step();

cf) requestAnimationFrameについて調べてみた

jQuery.easing プラグインを利用してイージングをかける

本題です。上のコードではイージングが一切かからない状態でアニメーションされます。 これにイージングをかけたいです。しかも楽をしてかけたい。すごくかけたい。

JavaScriptでのイージングといえば jQuery.easing プラグイン がおなじみですね。 このプラグインで宣言されるイージングの関数( $.easing.* )を使えば簡単に出来そうですが、 まずイージング関数に何を渡せばいいかを調べてみます。

実際にイージング関数に渡されている引数

jQueryにはじめから同梱されているイージングは “swing” と “linear” があります。 まずはこれらの関数で引数をどのようにとっているか、コードを拝見してみます。

jQuery.easing = {
    linear: function( p ) {
        return p;
    },
    swing: function( p ) {
        return 0.5 - Math.cos( p*Math.PI ) / 2;
    }
};

この p はどうやら開始値から終了値までの範囲で今どの地点にいるのかを渡しているみたいです。

では jQuery.easing プラグインではどのようになっているか見てみましょう。

easeOutQuad: function (x, t, b, c, d) {
    return -c *(t/=d)*(t-2) + b;
},

この “easeOutQuad” は “swing” の代替として宣言されている関数なわけですが、引数を見てみると全然数が違う上に、第一引数の “x” を使用していません。 jQuery.easing プラグイン のWebサイトを参照すると、右下の方に引数の解説が記載されています。 軽く拙訳を書いてみると、こんな感じみたいです。

jQuery.easing.method(
    null,          // 式では使用しない
    current_time,  // 現在の時間
    start_value,   // 開始値
    end_value,     // 終了値
    total_time     // 所要時間
)

スクロール量をベースにしてイージングをかけるためには、”current_time” と “total_time” をスクロール量におきかえてあげればうまくいきそうですね。

実際に簡単に動かしてみる

アニメーションを開始・終了するスクロール位置を定義してやり、その差を duration (“total_time”) として扱います。 現在のスクロール位置は、関数に渡す前にスクロール開始位置を引いてやりましょう。

/**
 * スクロール量が 500-1000 に差し掛かった時に
 * ".box" の "left" を 100-1000 の間でアニメーションさせる
 */
(function(){
    var box, start, end, from, to;

    box = $(".box");
    scrollStart = 500; // アニメーションを開始するスクロール位置
    scrollEnd = 1000;  // アニメーションを終了するスクロール位置
    from = 100;  // "left" の開始値
    to = 1000;   // "left" の終了値

    step = function(){
        var scroll, progress;
        scroll = $(window).scrollTop();
        if(scroll < scrollStart){
            box.css("left", from);
        } else if(scroll > scrollEnd){
            box.css("left", to);
        } else {
            // scroll と duration から現在位置を割合で取得
            progress = $.easing.easeOutQuad(
                null,
                scroll - scrollStart,
                0,
                1,
                scrollEnd - scrollStart
            );
            // 取得した割合を掛けて値を取得し、"left" に設定する
            box.css("left", from + (to - from) * progress);
        }
        requestAnimationFrame(step);
    };

    step();
}());

“linear” はどうなるのか

jQueryに同梱されているイージング関数2点のうち、”swing” は jquery.easing プラグインで再定義されているので問題ないのですが、 “linear” は上のコードのように使おうとすると引数が合わずに正常に動きません。

取り急ぎですが、引数を合わせた形で再定義してみます。

$.easing.linear = function(x, t, b, c, d){
    if(x !== null){ return x; }
    return b + ((c - b) * (t / d));
};

いろんなイージングで動かしてみたデモ

まとめ

スクロールアニメーションを操作するライブラリを先日見かけたのですが、 そのライブラリではいくつかのイージング関数を独自に定義していました。 (あろうことか、どのライブラリのコードを読んでいたのか、書いているうちに忘却してしまいました…)

せっかくなので様々なイージング関数を楽して使えたらな、と思い調べてみた記録でした。

コメント

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*