canvid.jsを使ってタッチデバイス向けの背景全面動画を実装する

少しずつ対象物の位置をずらした静止画像を連続的に切り替えると、対象物が動いているように見える錯覚を仮現運動といいます。わかりやすい例にパラパラ漫画があります。

通常、1秒当たり10フレーム以上の画像を表示させることで動画として認識させることができます。映画は24fps(毎秒24フレーム)で再生されます。フレーム数を上げると必要なデータ量は多くなりますが、より自然な動画体験を与えます。Webアプリケーション上のHTML5 VideoやGIFアニメーションも同じ原理で、静止画を連続表示することで動きのあるコンテンツを提供します。

動画コンテンツは訪問者により多くの情報をわかりやすく伝えることができ、訴求力や拡散力に優れているため、動画を活用したサイトが近年増えてきています。特に画面背景に動画を敷いたデザインはブランディング効果が高く、Webデザインのトレンドにもなりました。通信の高速化といった背景も動画コンテンツの活躍を後押ししてきた要因です。

タッチデバイスでの動画自動再生

とはいえまだ、すべてのデバイス間で同様の体験ができるわけではありません。ユーザーの意図しないパケット通信の発生を防ぐためにスマートフォンを始めとするタッチデバイスでの動画の自動再生は制限されており、事実、インターフェース上では無効化された状態で表示されます。大抵は動画の上に再生ボタンが重なって表示されます。

再生ボタンをクリックすると再生が開始されるのですが、iOSやAndroidは機種によって動画再生時に画面遷移が発生することもあるので、デザイナーが意図した見せ方ができない場合があります。例えば背景に動画を使ったWebサイトでは、再生ボタンにコンテンツが重なったり別画面で動画が再生されるという挙動を回避するために、タッチデバイスでは代替画像に置き換えたり、GIFアニメーションを利用するといったケースもあります。いずれも、グレイスフル・デグラデーションに基づいた代替案です。

GIFアニメーションのデメリット

ここでは全画面背景に動画を使ったWebサイトデザインに対して、PCとタッチデバイスどちらにも有効なアイデアを考えてみました。冒頭で紹介した仮現運動について振り返ると、動画表示のコンセプトは静止画を連続的に表示するというものでした。Photoshopを使うと、用意した複数の静止画を元にGIFアニメーションを簡単に作成することができます。

GIFアニメーションは一見有効な手段に見えますが、色数に制限があり動画を変換した際の劣化が目立つこと、また画質とフレーム数のバランスを保ちながらファイルサイズを抑えるのが難しいといった問題から、動画として全画面に表示させるには無理を感じました。さらに、ブラウザによってGIFアニメーションのフレームレートの限界が異なること、頭出しや一時停止など再生コントロールができないといった制限からも利用シーンが限られてきます。

canvid.jsとスプライト画像を使った動画再生

いくらかのリサーチの結果、canvid.jsとスプライト画像を使った手法を見つけました。 canvid.jsは、短い動画をcanvas上に再生するオープンソースの軽量なJSライブラリで、再生、一時停止、逆再生などの機能や、フレームレート、繰り返し再生、コールバックを設定することができます。canvid.jsは、あらかじめ用意されたスプライト画像を使って動画を表現しますが、JPGを利用することで、コンパクトなサイズで動画を再生することができます。 動画・音声エンコーダであるFFmpegと画像処理ソフトのImageMagickを使い、2行のコマンドで動画を1枚のスプライト画像に変換して用意します。公式サイトにより詳しい説明があります。

下記は実際に作成したサンプルの解説です。生成されるcanvasを格納するコンテナとして下記のdivをマークアップしておきます。

<div class="canvid-wrapper"></div>

canvid.jsを読み込み、次のような記述で利用します。

var canvidControl = canvid({
    videos: {
        clip1: {
            src: 'video.jpg',
            frames: 150,
            cols: 6,
            fps: 10,
            loops: 1,
        }
    },
    loaded: function() {
        canvidControl.play('clip1');
    }
});

必須オプションであるframesは、ffmpegで変換生成された画像の枚数、colsはffmpegコマンドで指定した列数を入れます。

例のように、フレームレートや再生ループ数も指定できます。今回は、ページの背景に全画面で動画を配置するため、下記のようなコードを書いてみました。(jQuery併用)

function calcRatio() {
    var w = $(window).width(),
        h = $(window).height();
    if (h >= w * 9 / 16) {
        $('.canvid-wrapper').addClass('nallow');
    } else {
        $('.canvid-wrapper').removeClass('nallow');
    }
}
function resizeFunc() {
    var timer = false;
    $(window).resize(function() {
        if (timer !== false) {
            clearTimeout(timer);
        }
        timer = setTimeout(function() {
            calcRatio();
        }, 200);
    });
}
var canvidControl = canvid({
    videos: {
        clip1: {
            src: 'video.jpg',
            frames: 150,
            cols: 6,
            fps: 10,
            loops: 0,
        }
    },
    loaded: function() {
        canvidControl.play('clip1');
        calcRatio();
        resizeFunc();
    }
});

calcRatio関数では、元となる動画の比率に対する画面サイズの比率を2パターンに分岐してスタイル用のクラスを切り替えます。元々の画像が16:9だったので、画面の幅にその比率を掛けた数値と画面の高さを比較しています。また、リサイズ時にも再計算するように、resizeFunc関数を用意しました。 両方の関数は、動画生成の処理が完了した後に実行されます。

CSSは下記のようにしました。

.canvid-wrapper,
.canvid-wrapper::after {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
}
.canvid-wrapper::after {
    display: block;
    content: '';
    background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFUlEQVQIW2NkYGCoZ2BgaGRkgIB6AAyoAYKa0AhQAAAAAElFTkSuQmCC) repeat;
}
.canvid {
    position: relative;
    top: 50%;
    left: 50%;
    width: 100%;
    height: auto;
    transform: translateY(-50%) translateX(-50%);
}

まずラッパーとなる.canvid-wrapperをウィンドウに対して100%の固定配置になるようにします。生成された.canvidは、親要素の.canvid-wrapperに対して中央配置になるように絶対配置とtransformプロパティを使って調整されています。デフォルトでは幅100%が指定されていますが、先ほどのcalcRatio関数でクラスnallowが付与された場合のみ、高さに合わせて伸張するので、ウィンドウがリサイズされても常に領域がカバーされます。また、大きいウィンドウサイズでも画質の劣化を目立ちにくくするために、after擬似要素を使って半透明のドットによるオーバーレイを動画の上に重ねています。

実際のサンプルはこちらからご確認ください。