JavaScriptで動画とコンテンツをfadein/fadeoutで切り替える


Webサイトにアクセスした際に、オープニングビデオのように動画を流してから、動画再生後にフェード効果でメインコンテンツを表示するなど、動画を活用することで文字情報だけでなく、動きのある映像で豊富な情報をわかりやすく伝えることができます。

フェード効果でのコンテンツ切り替えは、主にJavaScriptで実装していくことになります。
簡易的にスクリプトが書けるJavaScriptライブラリのjQueryを使う方法もありますが、純粋なJavaScriptでも動画コンテンツからメインコンテンツへのフェード効果での表示切り替えはできます。
意外と少ないコードで実装することができます。

ここからは、JavaScriptで動画とメインコンテンツをフェード効果で切り替える方法を、サンプルコードでご紹介していきます。

フェード効果でコンテンツを切り替える


HTML構造は、body要素内でWebページのコンテンツとオープニングビデオのコンテンツと、大きく2つのブロックで構成します。

以下、HTMLのサンプルコードです。

HTML

<div id="page-wrap">

  <header>
    <p>header</p>
  </header>

  <main>

    <section id="mv" class="section-conts">
      <h1>WELCOME!</h1>
    </section>

    <section id="intro" class="section-conts">
      <h2>Heading 2</h2>
    </section>

  </main>

  <footer>
    <p>footer</p>
  </footer>

</div>

<div id="opv-wrap">
  <video id="opv" autoplay muted>
    <source src="video/opening.mp4" type="video/mp4">
    <source src="video/opening.webm" type="video/webm">
  </video>
</div>

<script src="js/common.js"></script>


フェード効果の順番の影響を考慮するため、オープニングビデオの要素(div id=”opv-wrap”)はヘッダーやメインコンテンツ、フッター等、Webページのコンテンツブロックの下に、そしてスクリプトを記述していくJSファイルの読み込みの上に記述します。

続いてはCSS。
CSSでは、@keyframesを使ってフェードインやフェードアウトの効果を加えるようにします。
他、全体的なスタイルになります。

CSS

#opv-wrap {
  animation: fadeIn .5s ease;
}

#opv-wrap.playEnd {
  animation: fadeOut 1.5s ease;
}

video#opv {
  position: fixed;
  top: 0;
  left: 0;
  object-fit: cover;
  width: 100vw;
  height: 100vh;
  vertical-align: bottom;
}

#page-wrap {
  height: 100vh;
  overflow-y: hidden;
  animation: fadeIn 2s ease;
}

#page-wrap.startView {
  overflow-y: auto;
}

@keyframes fadeIn {
  0%{
    opacity: 0;
  }
  100%{
    opacity: 1;
  }
}

@keyframes fadeOut {
  0%{
    opacity: 1;
  }
  100%{
    opacity: 0;
  }
}

header {
  position: fixed;
  width: 100%;
  background-color: #e0e0e0;
  padding: 1rem 4%;
}

#mv {
  height: 100vh;
  background-color: rgb(216, 251, 254);
  display: flex;
  justify-content: center;
  align-items: center;
}

.section-conts {
  padding: 5rem 4%;
  height: 100vh;
}

.section-conts h2 {
  text-align: center;
}

footer {
  background-color: #e0e0e0;
  padding: 1rem 4%;
}


@keyframesでフェードインやフェードアウトの効果を、opacityプロパティを使って定義します。
オープニングビデオは、アクセスしたらフェードインが実装され動画が流れます。
playEndやstartViewのCSSクラスはJavaScriptで付与しますので、クラスが追加されたらフェードアウトのアニメーションを実装するようにしておきます。

1つポイントとしましては、
Webページのコンテンツ自体に高さがあれば、コンテンツの上に表示されている動画が流れている時もスクロールできてしまいます。
最初のオープニングビデオが流れている最中は、スクロールできたりスクロールバーが表示されないようにページコンテンツには「overflow-y: hidden;」を適応させ、動画再生終了後の動画がフェードアウトしてページコンテンツが表示された時に「overflow-y: auto;」でスクロールできるようにします。

最後はJavaScriptです。
なるべくSEOに影響を与えないため、オープニングビデオの要素はフェードアウト後、opacityプロパティで透過させて非表示にするだけではなく。dislayプロパティをnoneとして非表示にします。

JavaScriptのanimateメソッドを使ってopacetyやdisplayプロパティを操作する方法もありますが、SEOの観点からdisplayプロパティも必要とする中、opacityプロパティのフェード効果は問題ありませんが、JavaScriptではdisplayプロパティでフェードの表現がでません。
ここはCSSの@keyframesでフェードインやフェードアウトを実装させるため、JavaScriptではおもにクラスの付与でCSSのスタイルが適応されるようにします。

以下、サンプルコードになります。

JavaScript

const opvWrap = document.querySelector('#opv-wrap');
const opVideo = document.querySelector('video');
const pageConts = document.querySelector('#page-wrap');

opVideo.addEventListener('play', () => {

  const playTime = opVideo.duration * 1000 - 1000;
  const videoDuration = opVideo.duration * 1000;

  setTimeout(function(){
    opvWrap.classList.add("playEnd");
    pageConts.classList.add("startView");
  }, playTime);

  setTimeout(function(){
    opvWrap.style.display ="none";
  }, videoDuration);

});


オープニングビデオ全体の要素やビデオの要素、そしてページコンテンツと各要素をquerySelectorメソッドで取得して変数で管理していきます。

video要素を格納した変数「opVideo」に対して、「opVideo.addEventListener」で動画の再生イベントが発生したら処理を実装します。
変数「playTime」では、動画の時間(長さ)を取得できるdurationプロパティを使って、動画の秒数をミリ秒に計算しつつ、1秒(1000ミリ秒)を引いてフェードアウトが始まるオープニングビデオの再生時間を管理します。
変数「videoDuration」では、実際の動画の時間(長さ)を管理します。
これらの変数は、setTimeoutメソッドのタイマーの時間のdelay値の数値で利用していきます。

playTimeでセットされたタイマーでは、動画の再生時間終了の1秒前にCSSクラス「playEnd」を追加して、CSS側でフェードアウト処理を実行させます。
videoDurationでセットされたタイマーでは、動画が完全にフェードアウトしましたので、opacityプロパティでの透過だけでなくdisplayプロパティもnoneとしておきます。

以下、実装の動作なります。
動画(3分25秒)

まとめ


全体的な流れとしては、CSSの@keyframesでフェード効果を定義しておいて、JavaScriptで動画の終了のタイミングでクラスを付与してあげてCSSアニメーションを実装するといった感じです。

今回のサンプルでは、フェード効果のタイミングを1秒(1000ミリ秒)で調整していますが、お好みのタイミングがありましたらご自身のデザインに合わせてタイミングの秒数を調整してください。