某イカゲームの公式サイトなどでやってる手法です。
同じ件に遭遇するだろう同士の為にサンプル含めてメモっておきます。
See the Pen
YouTube Background by Tenderfeel (@Tenderfeel)
on CodePen.
サンプルをjsdo.itからCodePenに移動
YouTube IFrame API
利用するAPIは YouTube IFrame API です。
この公式のサイトにAPIを利用して動画を表示するサンプルがあるんで、それを適当にコピペすれば基本的な表示はできる感じになってます。
以下からは段階を追って冒頭に載せたCodePenのソースを適当に解説しています。
公式のリファレンス見てもよく分かんないという方向けです。
2018年9月25日以降の挙動について
以下2点の大きな変更があり、YouTube動画を背景に設定して利用することは実質できなくなっています。
showinfo
パラメータで動画のタイトル等を非表示にすることができなくなった。rel
の挙動が変更になり、0に設定した場合は表示している動画のチャンネル投稿動画からリストアップされるようになった。
この変更によりサンプルの挙動が変わりました。
- 再生開始でタイトルがチラ見え
- 一時停止で関連動画が表示される
API読み込み
IFrameAPIは、スクリプトタグで読み込みさせれば利用出来る代物になってますが、
スクリプトのロードが完了した次点で onYouTubeIframeAPIReady
メソッドが実行されるため、
ページ読み込みのタイミングにAPIの読み込みを合わせる必要があります。
なので公式のサンプルだとscriptタグを作ってsrcを設定し、最初に見つけたscriptタグの前に追加するという方法をとってます:
var tag = document.createElement('script'); tag.src = "https://www.youtube.com/iframe_api"; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
jQueryを使用しているとページを表示する準備ができた等のイベントは$(window).load
や$(document).ready
などで実行できます。サンプルで使ってるのは後者(の省略形)です。
そのイベントでscriptタグを追加すればいいのですが、追加する場所は割とどこでもいいので、jsdo.itのサンプルではbodyの一番下にしてあります:
$('body').append('<script src="https://www.youtube.com/iframe_api">');
動画プレイヤーの作成
まずはHTMLの方ですが、動画プレイヤーを表示する#player
を用意します。
<div id="player"></div>
APIの読み込みが完了されるとonYouTubeIframeAPIReady
が実行されるので、ここで動画プレイヤーオブジェクトを作成します。
動画プレイヤーを他の関数でも使える様にグローバル変数 player
に代入しています。
var () { player = new YT.Player('player', { videoId: '2ZBTVjhKr5E', playerVars: { 'autoplay': 1, 'controls': 0, 'enablejsapi': 1, 'iv_load_policy': 3, 'disablekb':1, 'showinfo':0, 'rel':0, 'start': 5, 'modestbranding': 1 }, events: { 'onReady': onPlayerReady, 'onStateChange': onPlayerStateChange } }); }; window.
YT.Playerクラスのパラメーターは次の通りです。
new YT.Player('プレイヤーを表示する要素のID', {オプション})
プレイヤーを表示する要素のIDは最初に用意した#player
にします。
実行された後に開発ツールなどでDOMを見ると、divだったのがiframeに変わっているのが分かると思います。
要素はdivではなくiFrameでもおkで、その場合はYouTubeの動画ページの埋め込みコードのソースをそのまま利用できます。
オプション
これらのオプションは省略できます。
- width(数値) — 動画プレイヤーの幅。デフォルトは640
- height(数値) — 動画プレイヤーの高さ。デフォルトは390
- videoId(文字列) — YouTubeで発行される動画のID
- playerVars(オブジェクト) — プレイヤーのカスタム用パラメーター
- events(オブジェクト) — イベントリスナーの指定
サンプルで指定したplayerVarsは次の通り:
playerVars: { 'autoplay': 1, //プレーヤーを読み込んだときに最初の動画を自動再生する 'controls': 0, //プレーヤーにプレーヤーコントロールを表示しない 'enablejsapi': 1, //JavaScript API が有効 'iv_load_policy': 3, //動画アノテーションを表示しない 'disablekb':1, //キーボード操作をOFF 'showinfo':0, //動画の再生が始まる前に動画のタイトルなどの情報を表示しない(廃止) 'rel':0, //再生終了時に関連動画を表示しない(0の場合は同じチャンネルの動画が表示される) 'start': 5 //00:05から再生する },
イベント
オプションで指定出来るイベントは6つです
onReady
— プレーヤーの読み込み完了時onStateChange
— プレイヤーの状態が変わった時- -1(未開始)
- 0(終了) –
YT.PlayerState.ENDED
- 1(再生中)-
YT.PlayerState.PLAYING
- 2(停止)-
YT.PlayerState.PAUSED
- 3(バッファリング中)-
YT.PlayerState.BUFFERING
- 5(頭出し済み)-
YT.PlayerState.CUED
onPlaybackQualityChange
— 動画の再生品質が変わった時onPlaybackRateChange
— 動画の再生速度が変わった時onError
— エラーが発生した時onApiChange
— プレーヤーが直接的な API メソッドでモジュールを読み込んだ(または読み込み解除した)時
サンプルでは、onReadyとonStateChangeを設定しています。
events: { 'onReady': onPlayerReady, 'onStateChange': onPlayerStateChange }
onReady
で指定したonPlayerReady
では、動画の音声をミュートにしています。
function onPlayerReady(event) { event.target.mute(); //音声をミュート }
onStateChange
で指定したonPlayerStateChange
では、動画の再生が終わった時にもう一度再生を実行して無限ループにしています。
function onPlayerStateChange(event) { if (event.data == YT.PlayerState.ENDED) { player.playVideo(); } }
動画を再生リストで指定する場合、playerVars
でloop:1
にすれば無限ループできますが、指定した動画が1つだけの場合はloop:1ではループされません。
表示サイズに動画サイズを合わせる
iFrameの横幅x高さをブラウザの表示サイズに合わせてリサイズする:
function resizeMovie () { var $w = $(window), bw = 1200, //基準にする横幅 bh = (bw/16) * 9, //基準にする高さ(16:9) w = $w.width(), //表示サイズ(幅) h = $w.height(), //表示サイズ(高さ) mw = w, //動画サイズ(幅) mh = Math.round(bh * (mw/bw)); //動画サイズ(高さ) if ( mh < h ) { //動画の高さが表示サイズの高さより小さかったら mh = h; //表示サイズの高さに変更 mw = Math.round(bw * (mh/bh)); //高さに合わせて横幅変更 } $('#player').css({ width: mw, height: mh, marginTop: (h - mh)/2, marginLeft: (w - mw)/2 }); } resizeMovie(); $(window).resize(resizeMovie);
YouTubeロゴが消せない問題
showinfoオプションでタイトルなんかは消せるものの、右下に表示されるYouTubeロゴは消せません。
表示領域より大きくして外にだしてしまうか、ロゴが消えるまでローディングで隠しておく必要があります。
サンプルでは後者でごまかしてます。
動画の上にローダー要素をかぶせる。
<div id="player"></div> <div id="player_cover"> <div id="loader"></div> <!--←これ--> </div>
ローダーは不透明がいいです。
#loader { background:#000 url('http://jsrun.it/assets/K/1/9/U/K19UZ.gif') no-repeat center center; position: absolute; top: 0; right: 0; bottom: 0; left: 0; }
onReady
で実行される関数内でローダーを非表示にすればおk。
読み込み完了から3秒くらいあればロゴが消えるのと入れ替わりになる。
function onPlayerReady(event) { $('#loader').delay(2500).animate({"opacity":0}, 800, "swing", function() { $(this).css('display', 'none'); }); event.target.mute(); }
コントローラー非表示&画面クリックで動画を一時停止とかする
マウスオーバーでコントローラー等が表示されるのを防ぐついでに画面クリックで動画操作をする。
動画の上にクリックイベントを付ける要素をかぶせる。
<div id="player"></div> <div id="player_cover"> <!--←これ--> <div id="loader"></div> </div>
その要素にクリックイベントでplayerを操作させる。
動画の状態はplayer.getPlayerState()
で取れるので、
帰ってきた値によって再生したりポーズしたりすればそれっぽくなります。
$('#player_cover').click(function() { switch(player.getPlayerState()) { case 1: player.pauseVideo(); break; default: player.playVideo(); } });
音量操作についても関数が用意されているので、同様の方法で再現できます。
ipadで再生しようとしたところずっとリロードになってしまします。ipadにも対応する方法があれば教えてください。
【追加】
また、iphone(スマホ)で動画をリピート再生する際、リピートの偶数回数ごとにスクリーンがフルスクリーンのようになって動画が終わるまで操作ができませんのでこちらも合わせ対応する方法がありましてら教えてください。
iOSおよびAndroidは動画の自動再生が出来ないので、読み込み中状態が続くのはプレイヤーの仕様です。(この記事はPC向けとして書いています)
リロードがページのリロードという意味ならあなたの実装になにか問題があるのだと思います。
youtube apiの挙動については開発者フォーラムで質問した方が有効な回答が得られると思います。
リロードは動画再生の方です。アンドロイドスマホでは、タップしても再生できなかったため、開発者フォーラムで質問してみたいと思います。お返事ありがとうございました!