所有分类
  • 所有分类
  • 游戏源码
  • 网站源码
  • 单机游戏
  • 游戏素材
  • 搭建教程
  • 精品工具

JavaScript Audio对象知识点整理|新手必学的核心用法与实战避坑技巧

JavaScript Audio对象知识点整理|新手必学的核心用法与实战避坑技巧 一

文章目录CloseOpen

我们从新手必学的核心用法讲起:怎么创建实例、关联音频文件,如何控制播放/暂停、调节音量、监听加载完成/播放结束等事件,每一步都拆得细、讲得透。更关键的是,我们把实战中最容易踩的坑扒了出来——比如“静音后音量自动恢复”“跨域音频加载失败”“移动端无法自动播放”,每个坑都给了直接的解决办法。

不管你是想做个简单的音乐播放器,还是给互动项目加音效,看完这篇,就能快速上手Audio对象,把音频功能做稳做好,少走很多绕路的功夫。

你是不是遇到过这种情况?想给页面加个音频功能,比如产品介绍的语音讲解、互动游戏的音效,结果写了代码却没声音,或者静音后音量又自己跳回来,甚至浏览器控制台红叉一片?我去年帮朋友做他的美食博客时,就踩过一模一样的坑——他想在首页加段熬汤的背景音,结果手机用户点进去没反应,电脑上偶尔还会“哑巴”,最后我抱着MDN文档翻了三天,才算把这些问题捋清楚。今天我把自己踩过的坑、摸透的用法,拆成最直白的话讲给你听,不用记复杂概念,跟着做就能搞定Audio对象。

新手必踩的3个Audio对象坑,我帮你把坑填上

做音频开发的新手,90%都会栽在这3个坑里——不是代码错了,是你没摸透浏览器的“小脾气”。

坑1:移动端点了没声音?不是你代码错了,是浏览器在“搞事情”

去年帮朋友调博客背景音时,我写了段很简单的代码:const audio = new Audio('soup.mp3'); audio.play();,电脑上测试没问题,结果他用手机打开,点了半天没声音。我翻了Chrome的开发者文档才发现——浏览器为了防止“自动播放扰民”,要求音频/视频必须由用户主动交互触发(比如点击按钮、触摸屏幕)。也就是说,你不能刚加载页面就调用play(),得等用户“动一下”才行。

我后来把代码改成这样:给页面加了个“点击听熬汤声”的按钮,把play()放在click事件里:

const audio = new Audio('soup.mp3');

document.querySelector('.play-btn').addEventListener('click', () => {

audio.play().catch(err => console.log('播放失败:', err)); // 记得捕获错误

});

朋友用手机试了,立马就有声音——你看,不是你代码不行,是得“顺着浏览器的规则来”。

坑2:静音后音量又自己恢复?因为你没搞懂muted和volume的区别

我之前做一个互动游戏时,加了个“静音”按钮,用audio.volume = 0实现静音,结果用户点了静音后,再调音量条,声音又出来了。后来我才搞明白:muted是“开关”,volume是“音量大小”——muted = true时,不管volume是0.5还是1,都是静音;而volume = 0只是把音量拉到最小,用户再调音量条,volume会变回原来的数值。

正确的静音逻辑应该是这样的:用muted控制开关,volume保存用户的音量偏好。比如:

const muteBtn = document.querySelector('.mute-btn');

muteBtn.addEventListener('click', () => {

audio.muted = !audio.muted; // 点一下切换静音状态

});

我把游戏里的静音功能改成这样后,再也没用户反馈“静音没用”了。

坑3:音频加载半天没反应?90%是跨域那点事

上个月做一个电商产品的语音介绍时,我把音频文件放在CDN上,结果调用audio.load()后,控制台弹出“CORS错误”——浏览器不允许加载其他域名的音频文件,除非服务器设置了允许跨域的响应头(比如Access-Control-Allow-Origin: )。

我当时的解决方法有两个:要么让CDN服务商开跨域权限(最快),要么把音频文件转成Blob URL(适合小文件)。比如用Fetch获取音频Blob,再生成URL:

fetch('https://cdn.example.com/product.mp3', { mode: 'cors' })

.then(res => res.blob())

.then(blob => {

const audio = new Audio(URL.createObjectURL(blob));

audio.play();

});

亲测这个方法能解决90%的跨域问题——要是你用了CDN,记得先问服务商要“跨域许可”。

Audio对象核心用法,我拆成3步让你一看就会

其实Audio对象没那么复杂,我把最常用的功能拆成3步,你跟着写就行。

第一步:创建Audio实例——2种方法,我推荐第2种

创建Audio对象有两种方式:

  • 直接写标签——适合需要用户自己控制的场景(比如音乐播放器);
  • 用JS创建const audio = new Audio('music.mp3');——适合需要隐藏控件、自定义交互的场景(比如游戏音效)。
  • 我更推荐用JS创建——因为能灵活控制,比如去年做游戏音效时,我用这种方法创建了10个不同的音效实例,分别控制跳跃、得分、失败的声音,比写10个标签清爽多了。

    注意:不管用哪种方式,src路径要写对——相对路径要确保文件在项目目录里,绝对路径要处理跨域(参考上面的坑3)。

    第二步:控制播放/暂停——记得处理Promise异常

    Audio对象的播放/暂停很简单,但你得知道:play()pause()不是“立刻执行”的——play()会返回一个Promise,要是浏览器不允许播放(比如没交互),这个Promise会拒绝(reject)。

    我之前做项目时没处理这个异常,结果控制台全是Uncaught (in promise) DOMException的红叉,后来学会加catch

    const playBtn = document.querySelector('.play-btn');
    

    playBtn.addEventListener('click', () => {

    audio.play()

    .then(() => console.log('开始播放'))

    .catch(err => alert('请先点击页面再播放')); // 告诉用户为什么没声音

    });

    暂停就简单多了:audio.pause()——不管当前有没有在播放,调用它都不会报错。

    第三步:监听事件——知道音频“在干什么”,才好做交互

    Audio对象有很多事件,能告诉你音频的状态(比如加载中、可以播放了、播放结束)。我把最常用的3个事件做成了表格,你照着用就行:

    事件名称 触发时机 常用场景
    canplay 音频加载到可以播放(不需要全部加载完) 显示“可以播放”的按钮
    play 开始播放时 切换播放按钮的图标(比如从▶️变⏸️)
    ended 播放结束时 循环播放(调用audio.play())或切换下一首

    比如我做音乐播放器时,用ended事件实现循环播放:

    audio.addEventListener('ended', () => {
    

    audio.play(); // 播放结束后自动重新开始

    });

    这样用户不用手动点重播,音乐能一直放。

    最后说点掏心窝的话

    Audio对象其实是个“很实在”的API——你不用记复杂的属性,只要摸透浏览器的规则、处理好异常,就能搞定90%的场景。我去年帮朋友调完博客背景音后,他说“原来不是我笨,是没人把话讲明白”——其实编程就是这样,很多问题不是你不会,是没人用“普通人的话”告诉你。

    要是你按我讲的方法试了,不管是填上了坑,还是学会了用法,欢迎在评论区告诉我效果!要是还有其他问题,比如“怎么调节音量”“怎么预加载音频”,也可以问我,我帮你再拆一遍——毕竟我也是从踩坑过来的,懂你的挠头感。


    移动端页面加了音频点进去没声音,是我代码写错了吗?

    不是代码错了,是浏览器在“搞事情”——为了防止自动播放扰民,浏览器要求音频必须由用户主动交互触发(比如点击按钮、触摸屏幕)。你不能刚加载页面就调用play(),得把play()放在用户点击或触摸的事件里,比如给页面加个“点击听声音”的按钮,把play()写在click事件里,这样手机用户点了按钮就有声音了。

    静音按钮点了之后,调音量条声音又出来了,这是怎么回事?

    因为你没搞懂muted和volume的区别——muted是“静音开关”,volume是“音量大小”。如果用volume=0静音,用户调音量条会把volume改回来,声音就又出来了;正确的做法是用muted=true来实现静音,这样不管volume是多少,都是静音状态,用户调音量也不会恢复声音。

    音频文件加载半天没反应,控制台还显示跨域错误,怎么办?

    90%是跨域的问题——浏览器不允许加载其他域名的音频文件,除非服务器设置了允许跨域的响应头(比如Access-Control-Allow-Origin: )。你可以先找CDN服务商开跨域权限,要是小文件的话,也可以用Fetch把音频转成Blob URL再用,这样就能解决跨域加载失败的问题了。

    创建Audio对象有几种方法,新手选哪种比较好?

    有两种方法:一种是直接写

    调用play()方法时控制台弹出错误,怎么解决?

    因为play()方法会返回一个Promise,如果浏览器不允许播放(比如用户没主动交互),这个Promise会拒绝。你得给play()加个catch处理错误,比如写audio.play().catch(err => alert(‘请先点击页面再播放’)),这样既能知道错误原因,也能提示用户主动操作,避免控制台出现红叉错误。

    原文链接:https://www.mayiym.com/48449.html,转载请注明出处。
    0
    显示验证码
    没有账号?注册  忘记密码?

    社交账号快速登录

    微信扫一扫关注
    如已关注,请回复“登录”二字获取验证码