javascript - 如何在没有 JavaScript 严格限制的情况下播放音频?
问题描述
我正在制作一个由纯 JavaScript 代码组成的游戏,我想在 JavaScript 中操作音频。具体来说,我想让页面在单击某些div
元素时以及在 JavaScript 代码中使用某些函数时开始播放音乐。
我知道 HTML5 的音频标签有一个限制,即如果Audio
没有用户单击音频元素的播放按钮,就无法播放与元素关联的音乐文件,所以我不能这样做:
const audio = document.createElement("audio");
audio.src = "url of source";
audio.play();
//Uncaught (in promise) DOMException: play() failed because
//the user didn't interact with the document first.
//https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
Chrome 的自动播放策略很简单:
始终允许静音自动播放。在以下情况下允许自动播放声音: 用户与域进行了交互(单击、点击等)。在桌面上,用户的媒体参与指数阈值已被超过,这意味着用户之前播放过有声视频。用户已将网站添加到移动设备的主屏幕或在桌面设备上安装 PWA。顶级框架可以将自动播放权限委托给其 iframe 以允许自动播放声音。
但我想更自由地管理音频,以制作好的游戏 UI。
为了实现我的目标,我认为我需要在 JavaScript 代码中引入另一个库或 API,或者仍然使用带有一些棘手提示的音频标签。
我在想其中一个选择可能是Web Audio API。
你能告诉我一些建议吗?
进步
我尝试了如下代码,当我使用 click 事件处理程序单击 div 元素时,它起作用了:
<div id="my-div">play</div>
<audio id="myAudio">
<source src="url of source" type="audio/mpeg">
</audio>
const myAudio = document.getElementById("myAudio");
const btn = document.getElementById("my-div");
btn.addEventListener("click",() => {
myAudio.play();
});
但是,当我像下面这样写时,即使我似乎没有违反自动播放策略,它也不会出现相同的错误:
document.getElementById('my-div').addEventListener('click', () => {
const audio = new Audio('url of source');
audio.play();
});
//Uncaught (in promise) DOMException: play() failed because
//the user didn't interact with the document first.
//https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
上面两个代码的主要区别是我是把音频源文件的url写在audio标签里还是写在audio标签里面的source标签里。我猜这会有所不同,但我不明白到底是什么问题。
解决方案
你是对的。只有在响应用户手势开始播放时,您才能确保播放不会被自动播放策略阻止。带有单击处理程序的按钮是经典示例,但单击处理程序也可以附加到 div。假设您的 div 有一个名为my-div
. 在这种情况下,以下应该工作。
document.getElementById('my-div').addEventListener('click', () => {
const audio = new Audio('url of source');
audio.play();
});
使用 Web Audio API 不会更改自动播放策略。无论使用哪种浏览器 API,通常都适用相同的规则。
推荐阅读
- android - InflateException 膨胀类 RadioButton 时出错
- php - Codeigniter 3 应用程序错误:无法将密码与 password_hash 匹配
- javascript - 为什么我的地理编码函数返回未定义?
- javascript - 如何将 semanti-ui 连接到 nuxt.js
- scala - 如何将嵌套对象从 rdd 行转换为一些自定义对象
- html - 具有屏幕宽度标题、限制宽度内容、弹性框徽标元素和粘性页脚的 HTML 页面
- python - Python中有没有办法遍历完整的脚本?
- node.js - 如何配置 TypeORM ormconfig.json 文件以解析 js dist 文件夹或 ts src 文件夹中的实体?
- r - 两行中 x 轴的图例
- python - 为什么我使用 `exec()` 的代码会引发错误?