サイト内全体で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を使えば対応できそうかなと思っています。
そのうち試してみます。
【参考サイト】
コメントが承認されるまで時間がかかります。