返回

P5.js 音乐播放器歌曲显示 undefined 问题解决

javascript

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. 检查文件路径

文件路径不对,肯定加载不出来。

操作步骤:

  1. 相对路径: 确认一下你的音频文件 (.mp3) 是不是和你的 HTML 文件 (或者 p5.js 项目文件) 在同一个文件夹里。如果在,直接写文件名就行了 (像上面代码那样)。
  2. 子文件夹: 如果音频文件在一个子文件夹里 (比如叫 "audio"),路径要写成 "audio/Burn The World Waltz.mp3" 这样。
  3. 绝对路径: 一般来说,不建议用绝对路径 (比如 C:/Users/MyName/Documents/MyProject/audio/Burn The World Waltz.mp3 ),因为换个电脑或者部署到服务器上,路径就变了。
  4. 使用开发者工具: 打开浏览器 (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 文件很常见,但还是确认一下:

  1. 文件是否损坏: 用别的播放器 (比如电脑自带的) 试试能不能正常播放。
  2. 浏览器兼容性: 换个浏览器 (Chrome, Firefox, Edge, Safari) 试试。
  3. 音频编码 有些不常见的音频编码,浏览器可能不认。

进阶技巧:错误处理

如果加载音频失败了,最好能给用户一个提示。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(),如果还有问题检查路径, 应该就能解决啦!