- 前言
- 背景音乐播放
- 1 自动播放
- 1 微信问题
- 2 Safari问题
- 3 解决方案代码
- 2 点击播放
- 1 自动播放
- 离开页面关闭音乐
- 缓存状态
- 1 客户端存储数据方法
- 2 示例
- 完整解决方案代码
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的数据存储,当用户关闭浏览器窗口后,数据会被删除。
详情请查看:http://www.w3school.com.cn/html5/html_5_webstorage.asp
(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>