サイト内全体でBGMを流したいときに問題になるのが、ページ遷移時にBGMを途切れないようにする方法です。
実現する方法としては、Ajaxで動的にHTMLを書き換える、iframeを使ってページ遷移しないようにする、Flashでサイト全体を構築するなどがあると思いますが、今回はiframeを使ってBGMを途切れないようにする方法を試してみます。
実装方法
iframeを使った実装方法ですが、親ページではaudioタグとiframe(幅高さ共に100%)のみ配置します。
iframe内に実際に表示するコンテンツを配置し、iframe内でページ遷移させることで、BGMを途切れさせずにページ遷移させることができます。
この実装方法の問題点としては、
- ページ遷移してもURLが書き変わらない
- ページ毎のURLが無いので、下層ページに直接アクセスすることができない
- 子ページに直接アクセスされた場合にBGMが鳴らない
などがありますが、今回は2と3を合わせて実装してみたいと思います。
今回作成するサンプルのディレクトリは以下のようにしています。
- index.html(親ページ)
- about
- index.html(子ページ)
- news
- index.html(子ページ)
- top
- index.html(子ページ)
- parent.js(親ページ用)
- underpage.js(子ページ用)
- parent.css(親ページ用)
- underpage.css(子ページ用)
子ページのディレクトリは一階層のみ、ファイル名はindex.htmlのみの想定です。
「/about/flow/flow01.html」のような場合は実装方法を少し変える必要があります。
親ページと子ページでそれぞれJavaScriptの処理を行いますので、iframeの親ページにはparent.jsを、子ページにはunderpage.jsというファイルを読み込ませます。
ページ遷移時にBGMを途切れさせないようにするデモページ
※BGMのオンオフは、ページ右上の「再生中」「停止中」をクリックで切り替えられます。
下層ページ用のURLを作成する
下層ページにもアクセスできるように、個別ページ用のURLをパラメータで作成してみます。
parent.js
/* ---------------------------------------- パラメータが付いているときの対応 ---------------------------------------- */ // iframeのid var frameId = 'baseFrame'; // ディレクトリ判別用パラメータの項目名 var judgment = 'page'; // ディレクトリ名(初期値はtop) var pageDir = 'top'; // パラメータが付いている場合 if(location.search.length) { // パラメータの分解 var params = location.search.substring(1).split('&'); for (var i = 0; i < params.length; i++) { var paramName = params[i].split('='); // パラメータの項目名が指定したものだった場合 if(paramName[0] == judgment) { // 表示するページのディレクトリを取得 pageDir = paramName[1]; } } // iframeのURL書き換え document.getElementById(frameId).src = './' + pageDir + '/'; }
下層ページ(about)にアクセスするデモ
下層ページ(news)にアクセスするデモ
子ページに直接アクセスしたときの対応
子ページでは、iframeで読み込まれているかどうかを判断して、iframeから読み込まれていない場合はリダイレクト(上記で設定したパラメータ付きURL)をするようにします。
underpage.js
/* ---------------------------------------- 個別ページに直接アクセスしたときの対応 ---------------------------------------- */ // ディレクトリ判別用パラメータの項目名 var judgment = 'page'; // iframeから読み込まれていない場合 if(window == parent) { //URLを取得 var url = location.href.split('/'); // URLから表示ページのディレクトリ名を取得 var directory = url[url.length - 2]; var redirect = ''; // リダイレクトするURL(パラメータなし)を作成 for (var i = 0; i < url.length - 2; i++) { redirect += url[i] + '/'; } // パラメータ付きのURLにリダイレクトさせる location.href = redirect + '?' + judgment + '=' + directory; }
子ページ(about)に直接アクセスした場合のデモ
子ページ(news)に直接アクセスした場合のデモ
子ページから親ページのBGMを制御
子ページからBGMの一時停止や再生などをさせたい場合や、前回アクセス時のBGMの状態(再生していたか停止させていたか)を継続させたい場合などあると思いますので、合わせて実装してみます。
前回のBGMの状態を記憶させるためにcookieを使用します。
JavaScript
/* ---------------------------------------- BGMの制御 ---------------------------------------- */ // 有効期限日数 var cookiePeriod = 1; // ドメイン名 var cookieUrl = 'cly7796.net'; // cookieの設定 function setCookie(val) { $.cookie('bgm', val, { expires: cookiePeriod, path:'/', domain: cookieUrl }); } var audio = window.parent.document.getElementById('audio'); var bgm = window.document.getElementById('bgm'); // BGM再生 function bgmPlay() { audio.play(); bgm.innerHTML = '<span class="play">再生中</span>'; } // BGM停止 function bgmPause() { audio.pause(); bgm.innerHTML = '<span class="stop">停止中</span>'; } $(function() { // 1回目のアクセス if($.cookie('bgm') == undefined) { setCookie('on'); // 2回目以降のアクセス } else { } // アクセス時のBGM判別 if($.cookie('bgm') == 'off') { bgmPause(); } else { bgmPlay(); } // BGMの切り替え $(document).on('click', '#bgm', function() { if($.cookie('bgm') == 'off') { bgmPlay(); setCookie('on'); } else { bgmPause(); setCookie('off'); } }); });
ページ右上の「再生中」「停止中」をクリックすることで、BGMのオンオフを切り替えられます。
ページ遷移時にBGMを途切れさせないようにするデモページ
問題点の1で挙げた ページ遷移してもURLが書き変わらない件は、まだ試していませんがpushStateとパラメータ付きURLを使えば対応できそうかなと思っています。
そのうち試してみます。
【参考サイト】
コメントが承認されるまで時間がかかります。