1. 程式人生 > >H5背景音樂解決方案

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] 微信問題

解決方案:監聽WeixinJSBridgeReadyDOMContentLoaded事件

【微信的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>