ウェブ アニメーションの再生コントロール(Chrome 39)

今年の初めに、Chrome 36 で element.animate メソッドが導入されました。これは、より広範な ウェブ アニメーション仕様の一部です。これにより、命令型で記述された効率的なネイティブ アニメーションが可能になり、デベロッパーは、アニメーションと遷移を最も適した方法で構築できるようになりました。

以下に、画面全体に雲をアニメーション化して、完了時にコールバックを実行する方法を示します。

var player = cloud.animate([
    {transform: 'translateX(' + start + 'px)'},
    {transform: 'translateX(' + end + 'px)'}
], 5000);
player.onfinish = function() {
    console.info('Cloud moved across the screen!');
    startRaining(cloud);
};

この方法は非常に簡単で、アニメーションや遷移を強制的に作成する際にツールボックスの一部として検討する価値があります。ただし、Chrome 39 では、element.animate から返される AnimationPlayer オブジェクトに再生コントロール機能が追加されました。これまでは、アニメーションを作成した後は、cancel() を呼び出すか、終了イベントをリッスンすることしかできませんでした。

これらの再生機能の追加により、Web アニメーションの可能性は大きく広がります。アニメーションは、遷移を規定するのではなく、「固定」または事前定義されたアニメーション。

一時停止、巻き戻し、再生速度の変更

まず、上記の例を更新して、雲をクリックするとアニメーションを一時停止するようにします。

cloud.addEventListener('mousedown', function() {
    player.pause();
});

playbackRate プロパティを変更することもできます。

function changeWindSpeed() {
    player.playbackRate *= (Math.random() * 2.0);
}

reverse() メソッドを呼び出すこともできます。これは通常、現在の playbackRate を反転(-1 を掛ける)と同等です。ただし、次のような特殊なケースがあります。

  • reverse() メソッドによる変更によって実行中のアニメーションが事実上終了する場合、currentTime も反転します。たとえば、まったく新しいアニメーションを逆にすると、アニメーション全体が逆再生されます。

  • プレーヤーが一時停止している場合は、アニメーションの再生が開始されます。

プレーヤーのスクラブ

AnimationPlayer で、アニメーションの実行中に currentTime を変更できるようになりました。通常、この値は時間の経過とともに増加します(playbackRate が負の値の場合は減少します)。これにより、アニメーションの位置を外部から制御できます(ユーザー操作など)。これは一般に「スクラブ」と呼ばれます。

たとえば、HTML ページで空を表していて、ドラッグ操作で現在再生中の雲の位置を変更したい場合は、ドキュメントにハンドラを追加します。

var startEvent, startEventTime;
document.addEventListener('touchstart', function(event) {
    startEvent = event;
    startEventTime = players.currentTime;
    player.pause();
});
document.addEventListener('touchmove', function(event) {
    if (!startEvent) return;
    var delta = startEvent.touches[0].screenX -
        event.changedTouches[0].screenX;
    player.currentTime = startEventTime + delta;
});

ドキュメントの上にドラッグすると、元のイベントからの距離を反映して currentTime が変更されます。ジェスチャーが終了したときにアニメーションの再生を再開することもできます。

document.addEventListener('touchend', function(event) {
    startEvent = null;
    player.play();
});

ページからマウスを離した場所に応じて、この動作をリバース動作と組み合わせることもできます(組み合わせたデモ)。

ユーザー操作に応じて AnimationPlayer をスクラブする代わりに、その currentTime を使用して進行状況やステータス(ダウンロードのステータスなど)を表示することもできます。

AnimationPlayer を使用すると、値を設定でき、基盤となるネイティブ実装が進捗状況の可視化を処理します。ダウンロードの場合、アニメーションの長さを合計ダウンロード サイズに設定し、currentTime を現在ダウンロードされているサイズ(デモ)に設定できます。

UI の遷移とジェスチャー

モバイル プラットフォームでは長い間、ドラッグ、スライド、スワイプなどの一般的なジェスチャーが使用されてきました。これらのジェスチャーには、リストビューの「プルして更新」や画面の左側から引き出されるサイドバーなど、ドラッグ可能な UI コンポーネントという共通のテーマがあります。

ウェブアニメーションを使用すると、パソコンでもモバイルでも、ウェブ上で同様の効果を簡単に再現できます。たとえば、currentTime を制御するジェスチャーが完了すると、次のように処理されます。

var steps = [ /* animation steps */ ];
var duration = 1000;
var player = target.animate(steps, duration);
player.pause();
configureStartMoveListeners(player);

var setpoints = [0, 500, 1000];
document.addEventListener('touchend', function(event) {
    var srcTime = player.currentTime;
    var dstTime = findNearest(setpoints, srcTime);
    var driftDuration = dstTime - srcTime;

    if (!driftDuration) {
    runCallback(dstTime);
    return;
    }

    var driftPlayer = target.animate(steps, {
    duration: duration,
    iterationStart: Math.min(srcTime, dstTime) / duration,
    iterations: Math.abs(driftDuration) / duration,
    playbackRate: Math.sign(driftDuration)
    });
    driftPlayer.onfinish = function() { runCallback(dstTime); };
    player.currentTime = dstTime;
});

これにより、ドリフトを実行する追加のアニメーションが作成されます。これは、ジェスチャーが完了した場所から、既知の正常なターゲットまで再生されます。

これは、アニメーションが作成順序に基づいて優先度が決まるためです。この場合、driftPlayer は player よりも優先されます。driftPlayer が完了すると、driftPlayer とその効果は消えます。ただし、最終的な時間は基盤となるプレーヤーの currentTime と一致するため、UI は一貫したままになります。

最後に、子猫が好きな方のために、これらのジェスチャーを試すことができるデモ ウェブ アプリケーションも用意されています。モバイル フレンドリーで、下位互換性のためにポリフィルを使用しているため、モバイル デバイスで読み込んでみてください。

さあ、element.animate を試してみましょう。

element.animate メソッドは、シンプルなアニメーションに使用する場合でも、返された AnimationPlayer を他の方法で活用する場合でも、今すぐ試す価値があります。

これらの 2 つの機能は、他の最新のブラウザでも軽量なポリフィルを介して完全にサポートされています。このポリフィルは機能検出も実行するため、ブラウザ ベンダーが仕様を実装するにつれて、この機能は時間の経過とともに高速化と改善を重ねていきます。

Web Animations の仕様も引き続き進化していきます。今後の機能を試してみたい場合は、より詳細なポリフィル: web-animations-next でも利用できます。