P5.js 音乐播放器歌曲显示 undefined 问题解决
2025-03-18 03:20:23
P5.js 音乐播放器:歌曲显示为 undefined 的问题解决
做课程作业,要用 p5.js 弄个音乐播放器。我在网上找了个教程,基本照着抄的(只是改了改,让它能播放多首歌曲)。可是播放按钮就是不好使。 啥原因导致它读不出我的文件呢?
问题原因分析
遇到 undefined
,八成是加载音频文件出了岔子。loadSound()
函数是异步的,意思就是说,它开始加载文件了,不等加载完,就接着往下执行代码了。
这样一来,可能出现啥情况? setup()
还没加载完音频,mousePressed
对应的函数已经尝试播放了。 这时, song1
,song2
... 就有可能是 undefined
.
另外几个需要留意的地方:
- 文件路径错了没?
- 文件名写对了没? (大小写要注意!)
- 文件是不是真在那个路径下?
- 浏览器是否支持这个音频格式 (.mp3 一般是没问题的)?
解决方案
下面是几种解决方法,咱们一个个试试:
1. 使用 preload()
函数
p5.js 有个 preload()
函数, 它能保证在 setup()
执行 之前 加载完所有资源。 把加载音频的代码放到 preload()
里头,就能保证音频文件在用之前加载好了。
原理: preload()
函数会在 setup()
和 draw()
之前执行,确保所有资源都已就绪。
代码示例:
var track = 1;
let song1, song2, song3, song4, song5;
let title = ""; // 初始化 title
function preload() {
song1 = loadSound('Burn The World Waltz.mp3');
song2 = loadSound('Le Grande Chase.mp3');
song3 = loadSound('Mesmerizing Galaxy.mp3');
song4 = loadSound('Guzheng City.mp3');
song5 = loadSound('Holiday Weasel.mp3');
}
function setup() {
createCanvas(500, 250);
//setup play
let playButton;
playButton = createButton('>||');
playButton.size(100, 100);
playButton.position(200, 150);
playButton.style('background:green');
playButton.mousePressed(toggleSong);
//setup shift_track_right
let rightButton;
rightButton = createButton('>>|');
rightButton.size(100, 100);
rightButton.position(300, 150);
rightButton.style('background:cyan');
rightButton.mousePressed(right);
//setup shift_track_left
let leftButton;
leftButton = createButton('|<<');
leftButton.size(100, 100);
leftButton.position(100, 150);
leftButton.style('background:cyan');
leftButton.mousePressed(left);
}
function left() {
if (track > 1) { // 修正这里的逻辑错误
track -= 1;
}
}
function right() {
if (track < 5) { // 修正这里的逻辑错误
track += 1;
}
}
function toggleSong() {
let currentSong;
if (track === 1) {
currentSong = song1;
} else if (track === 2) {
currentSong = song2;
} else if (track === 3) {
currentSong = song3;
} else if (track === 4) {
currentSong = song4;
} else if (track === 5) {
currentSong = song5;
}
if (currentSong) { // 检查 currentSong 是否有效
if (currentSong.isPlaying()) {
currentSong.stop();
} else {
currentSong.play();
}
}
}
function draw() {
background(220);
if (track === 1)
{
title = 'Burn the World Waltz';
}
else if (track === 2)
{
title = 'Le Grand Chase';
}
else if (track === 3)
{
title = 'Mesmerizing Galaxy';
}
else if (track === 4)
{
title = 'Guzheng City';
}
else if (track === 5)
{
title = 'Holiday Weasel';
}
textSize(25)
text(title, 100, 100)
}
改进说明:
preload()
函数: 把所有loadSound()
调用都移到preload()
函数里。left()
和right()
函数修正 : 更正了left()
和right()
中不正确的条件检查, 避免track
超出范围。- 简化
toggleSong()
: 用currentSong
变量简化代码逻辑。 - 增加
currentSong
检查 增加安全性。
2. 检查文件路径
文件路径不对,肯定加载不出来。
操作步骤:
- 相对路径: 确认一下你的音频文件 (.mp3) 是不是和你的 HTML 文件 (或者 p5.js 项目文件) 在同一个文件夹里。如果在,直接写文件名就行了 (像上面代码那样)。
- 子文件夹: 如果音频文件在一个子文件夹里 (比如叫 "audio"),路径要写成
"audio/Burn The World Waltz.mp3"
这样。 - 绝对路径: 一般来说,不建议用绝对路径 (比如
C:/Users/MyName/Documents/MyProject/audio/Burn The World Waltz.mp3
),因为换个电脑或者部署到服务器上,路径就变了。 - 使用开发者工具: 打开浏览器 (Chrome, Firefox 等) 的开发者工具 (按 F12),在 "Network" (网络) 选项卡里,看看加载音频文件的时候有没有报错 (比如 404 Not Found)。
3. 使用回调函数 (Callback)
loadSound()
函数可以接受一个回调函数作为参数。这个回调函数会在音频加载 完成之后 被调用。可以用这个办法来确保音频加载完再进行下一步操作。
原理: 回调函数提供了一种处理异步操作完成的机制。
代码示例:
// ... (其他代码和 preload() 函数一样) ...
function setup() {
createCanvas(500, 250);
//setup play
let playButton;
playButton = createButton('>||');
playButton.size(100, 100);
playButton.position(200,150);
playButton.style('background:green');
playButton.mousePressed(toggleSong);
//setup shift_track_right
let rightButton;
rightButton = createButton('>>|');
rightButton.size(100, 100);
rightButton.position(300,150);
rightButton.style('background:cyan');
rightButton.mousePressed(right);
//setup shift_track_left
let leftButton;
leftButton = createButton('|<<');
leftButton.size(100, 100);
leftButton.position(100,150);
leftButton.style('background:cyan');
leftButton.mousePressed(left);
// 例子:给 song1 设置回调函数
song1 = loadSound('Burn The World Waltz.mp3', songLoaded);
// ... 其他歌曲也可以设置回调函数 ...
}
function songLoaded()
{
console.log("song 1 loaded");
}
//其他代码和 方法一 相同.
说明:
- 在这个例子里,
songLoaded
函数就是回调函数。song1 = loadSound('Burn The World Waltz.mp3', songLoaded);
这行代码的意思是:加载完 'Burn The World Waltz.mp3' 之后,调用songLoaded
函数。 你可以在songLoaded
里写加载成功后需要执行的代码 (比如开始播放,或者显示一条消息)。 - 推荐把所有的按钮设置移动到
setup()
。
4. 检查文件和浏览器兼容性
虽然 .mp3 文件很常见,但还是确认一下:
- 文件是否损坏: 用别的播放器 (比如电脑自带的) 试试能不能正常播放。
- 浏览器兼容性: 换个浏览器 (Chrome, Firefox, Edge, Safari) 试试。
- 音频编码 有些不常见的音频编码,浏览器可能不认。
进阶技巧:错误处理
如果加载音频失败了,最好能给用户一个提示。loadSound()
函数还可以接受 第二个 回调函数,作为错误处理函数。
代码示例:
function preload() {
song1 = loadSound('Burn The World Waltz.mp3', songLoaded, loadError);
// ... 其他歌曲 ...
}
function songLoaded() {
console.log("Song loaded successfully!");
}
function loadError(error) {
console.error("Error loading song:", error);
// 这里可以显示错误信息给用户,比如:
// text("加载音频失败!", 100, 100);
}
//其他和上面一致
说明:
如果加载过程中发生了错误,就会调用 loadError
,并且把错误信息传给它。 这样可以更好地处理加载失败的情况。
总结一下, 先把音频加载代码放进preload()
,如果还有问题检查路径, 应该就能解决啦!