video要素のロード中はローディング表示をしてロード完了後に再生を行う
結論
ソースコードはこちら。
ローディング表示はvideo要素の裏に表示させておくことで対応してください。
<script>
window.addEventListener('DOMContentLoaded', (event) => {
var video = document.querySelector('video');
if (video.readyState >= 3) {
// ビデオの読み込みが既に完了している場合
document.body.classList.add('loaded');
video.play();
} else {
// ビデオの読み込みが完了するまで 'canplaythrough' イベントを監視
video.addEventListener('canplaythrough', function() {
document.body.classList.add('loaded');
video.play();
});
}
});
</script>
<style>
video {
transition: .2s opacity;
}
body:not(.loaded) video {
opacity: 0;
}
body.loaded video {
opacity: 1;
}
</style>
<video src="path/video.mp4" loop muted playsinline></video>
詳細
video要素を背景として使用する場合、次のようなコードを使用すると思います。
<video src="path/video.mp4" autoplay loop muted playsinline></video>
これには次のような問題があります。
- ロード中は表示されない
- 十分にバッファされるまでの間、最初のフレームが静止画として表示される
環境によって挙動は異なると思いますが、自分が確認したのが上記です。
ロード中に表示されない件は、video要素の背景にローディングのエフェクトを隠しておけば良いとして、問題なのは二番目のバッファされるまでの間、最初のフレームが静止画として表示される件。
これはautoplay属性がそのような挙動を示すようだったので、autoplay属性ではなくjavascriptで再生の制御をすることにしました。
var video = document.querySelector('video');
// videoの読み込み完了時に発火
video.addEventListener('canplaythrough', function() {
// bodyにloadedクラスをつける
document.body.classList.add('loaded');
// 再生
video.play();
});
しかし、上記コードではcanplaythroughが発火しない場合がありました。
どうやら、キャッシュを読みこんだ際はcanplaythroughなどのイベントは取得できないようで、
再生が開始されない不具合がありました。そこで次のコードになりました。
<script>
window.addEventListener('DOMContentLoaded', (event) => {
var video = document.querySelector('video');
if (video.readyState >= 3) {
// ビデオの読み込みが既に完了している場合
document.body.classList.add('loaded');
video.play();
} else {
// ビデオの読み込みが完了するまで 'canplaythrough' イベントを監視
video.addEventListener('canplaythrough', function() {
document.body.classList.add('loaded');
video.play();
});
}
});
</script>
<style>
video {
transition: .2s opacity;
}
body:not(.loaded) video {
opacity: 0;
}
body.loaded video {
opacity: 1;
}
</style>
--
以上