H5背景音樂解決方案
1. 前言
很多H5的專案會用到背景音樂,雖然是很小的一個模組,但是有不少的坑。本文總結了背景音樂的常用情況的解決方案。
在進行下面內容之前,如果你並不瞭解Audio,可以參考之前的文章:
淺談Audio
2. 背景音樂播放
我們用最簡單的方式來播放音樂:
<!DOCTYPE html>
<html>
<body>
<audio id='audio' src='http://go.163.com/2018/0209/mengniu/audio/bgm.mp3' autoplay loop>
</audio>
</body >
</html>
或者:
<!DOCTYPE html>
<html>
<body>
<audio id='audio' src='http://go.163.com/2018/0209/mengniu/audio/bgm.mp3' loop>
</audio>
<script>
var audio = document.getElementById('audio');
audio.play();
</script>
</body>
</html >
結果,在瀏覽器中可以自動播放,但是在移動端的微信和safari中都無效。
原因:為了節省流量
1、大部分iOS和少部分Android的微信
2、部分Android瀏覽器和所有iOS系統的Safari
不支援自動播放音訊視訊
那麼,如何解決這樣的問題呢?
(1) 自動播放
[1] 微信問題
解決方案:監聽WeixinJSBridgeReady
和DOMContentLoaded
事件
【微信的JS API建立在微信殼瀏覽器的內建JS物件WeixinJSBridge上,WeixinJSBridge並不是WebView一開啟就有了,客戶端需要初始化這個物件,當這個物件準備好的時候,客戶端會丟擲事件”WeixinJSBridgeReady”。
發現部分機型,監聽DOMContentLoaded和load事件,在回撥中也可以播放音樂;
所以,為了保險起見,可以同時監聽兩個事件,以增強其適用性。】
——摘自 https://www.cnblogs.com/wmhuang/p/5452259.html
[2] Safari問題
解決方案:監聽touchstart
事件,在使用者點選螢幕的時候開始播放音樂
[3] 解決方案程式碼
//--建立頁面監聽,等待微信端頁面載入完畢 觸發音訊播放
document.addEventListener('DOMContentLoaded', function () {
function audioAutoPlay() {
var audio = document.getElementById('audio');
audio.play();
document.addEventListener("WeixinJSBridgeReady", function () {
audio.play();
}, false);
}
audioAutoPlay();
});
//--建立觸控監聽,當瀏覽器開啟頁面時,觸控式螢幕幕觸發事件,進行音訊播放
function audioAutoPlay() {
var audio = document.getElementById('audio');
audio.play();
document.removeEventListener('touchstart',audioAutoPlay);
}
document.addEventListener('touchstart', audioAutoPlay);
(2) 點選播放
上述解決方案存在的問題是,desktop和mobile瀏覽器中行為不一致,也就是說,在desktop的瀏覽器裡面音樂是自動播放的,而mobile的safari要觸摸了螢幕才會播放。
之前提到,為了節省流量不會自動播放,那麼就意味著有使用者互動是可以播放的。
所以,這個解決方案是,誘導使用者互動,從而播放音樂。最常見的是,在頁面中出現按鈕,需要使用者去點選。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
</head>
<body>
<audio id='audio' src='http://go.163.com/2018/0209/mengniu/audio/bgm.mp3' loop></audio>
<button id='button' onclick='playBgMusic()'>點我開始播放</button>
<script>
function playBgMusic(){
var audio=document.getElementById('audio');
audio.play();
}
</script>
</body>
</html>
3. 離開頁面關閉音樂
在mobile的safari中開啟頁面,聽到了播放的背景音樂,無意中按了home鍵退出,WHAT!!音樂還在放。顯然,這樣不合理。
解決方案: 通過document.hidden
屬性判斷當前頁面是否是啟用狀態
相容性:IE10+,Firefox10+,Chrome14+,Opera12.1+,Safari7.1+
下面給出例子,這樣可以判斷使用者是否還在這個頁面。用這個方法就可以控制音樂的關閉和播放了。
var hiddenProperty = 'hidden' in document ? 'hidden' :
'webkitHidden' in document ? 'webkitHidden' :
'mozHidden' in document ? 'mozHidden' :
null;
var visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange');
var onVisibilityChange = function(){
if (!document[hiddenProperty]) {
document.title='啟用狀態';
}else{
document.title='離開頁面啦';
}
}
document.addEventListener(visibilityChangeEvent, onVisibilityChange);
注意:微信中播放狀態,按home鍵後音樂還是會播放。
4. 快取狀態
常見的有背景音樂的專案中,通常會有一個關閉背景音樂的開關。如何能記住使用者的選擇,在重新整理頁面的時候,還能保持原來的選擇狀態呢?
(1) 客戶端儲存資料方法
HTML5 提供了兩種在客戶端儲存資料的新方法:
localStorage
- 沒有時間限制的資料儲存
sessionStorage
- 針對一個session的資料儲存,當用戶關閉瀏覽器視窗後,資料會被刪除。
(2) 示例
使用者第一次進入頁面,會顯示‘還沒選’,當用戶選擇了播放或者暫停後,再重新整理頁面,會記住使用者之前的選擇。只有當關掉頁面後,再重新進入才會再顯示‘還沒選’。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
</head>
<body>
<audio id='audio' src='http://go.163.com/2018/0209/mengniu/audio/bgm.mp3' loop></audio>
<button onclick='playBgMusic()'>點我播放</button>
<button onclick='pauseBgMusic()'>點我暫停</button>
<p>使用者選擇:<span id='status'></span></p>
<script>
var audio=document.getElementById('audio');
//初始化判斷
if(sessionStorage.bgmusic=='play'){
audio.play();
document.getElementById('status').innerHTML='播放';
}else if(sessionStorage.bgmusic=='pause'){
audio.pause();
document.getElementById('status').innerHTML='暫停';
}else{
document.getElementById('status').innerHTML='還沒選';
}
//播放函式
function playBgMusic(){
audio.play();
sessionStorage.bgmusic='play';
document.getElementById('status').innerHTML='播放';
}
//暫停函式
function pauseBgMusic(){
audio.pause();
sessionStorage.bgmusic='pause';
document.getElementById('status').innerHTML='暫停';
}
</script>
</body>
</html>
上例中使用的是sessionStorage,如果使用localStorage方法的話,在已選之後,只有清掉快取才能回到‘還沒選’的狀態。
5. 完整解決方案程式碼
以下是完整的背景音樂自動播放的解決方案,並且有模擬音樂開關的按鈕。
說明:safari下初始化按鈕顯示‘正在播放’,但並沒有聲音,當用戶觸控到螢幕時,聲音才播放。若使用者一次觸控式螢幕幕就是按鈕位置,則按鈕顯示‘停止播放了’,這時沒有背景音樂;再點一次,按鈕顯示‘正在播放’,同時播放。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
</head>
<body>
<audio id='audio' src='http://go.163.com/2018/0209/mengniu/audio/bgm.mp3' loop></audio>
<button id='status' onclick='triggerBgMusic()'>播放按鈕</button>
<script>
//----------頁面初始化------------
var audio = document.getElementById('audio');
if(sessionStorage.bgmusic=='pause'){
playBgMusic(false);
}else{
playBgMusic(true);
//----------處理自動播放------------
//--建立頁面監聽,等待微信端頁面載入完畢 觸發音訊播放
document.addEventListener('DOMContentLoaded', function () {
function audioAutoPlay() {
playBgMusic(true);
document.addEventListener("WeixinJSBridgeReady", function () {
playBgMusic(true);
}, false);
}
audioAutoPlay();
});
//--建立觸控監聽,當瀏覽器開啟頁面時,觸控式螢幕幕觸發事件,進行音訊播放
function audioAutoPlay() {
playBgMusic(true);
document.removeEventListener('touchstart',audioAutoPlay);
}
document.addEventListener('touchstart', audioAutoPlay);
}
//----------處理頁面啟用------------
var hiddenProperty = 'hidden' in document ? 'hidden' :
'webkitHidden' in document ? 'webkitHidden' :
'mozHidden' in document ? 'mozHidden' :
null;
var visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange');
var onVisibilityChange = function(){
if (!document[hiddenProperty]) {
if(!sessionStorage.bgmusic||sessionStorage.bgmusic=='play'){
audio.play();
}
}else{
audio.pause();
}
}
document.addEventListener(visibilityChangeEvent, onVisibilityChange);
//---------背景音樂開關----------
function triggerBgMusic(){
if(!sessionStorage.bgmusic||sessionStorage.bgmusic=='play'){
playBgMusic(false);
}else{
playBgMusic(true);
}
}
//---------音樂播放和暫停----------
function playBgMusic(val){
if(val){
audio.play();
sessionStorage.bgmusic='play';
document.getElementById('status').innerHTML='正在播放';
}else{
audio.pause();
sessionStorage.bgmusic='pause';
document.getElementById('status').innerHTML='停止播放了';
}
}
</script>
</body>
</html>