当前位置:   article > 正文

使用 Electron 构建跨平台的音乐播放器

使用 Electron 构建跨平台的音乐播放器

本文将介绍如何使用 Electron 实现音乐播放器的基本功能,包括音乐文件的加载、播放控制和界面展示等。

一、准备工作

首先确保你已经安装了 Node.js 和 npm。

1.1 创建项目目录

创建一个新的项目目录名为“music-player”

1.2 初始化项目

使用vscode打开项目(可以使用其他开发工具),在当前目录的终端命令行输入:

npm init -y

来进行项目的初始化。

1.3 安装Electron

通过以下命令安装 Electron:

npm install electron

如果上面命令不好使可以用这个:

cnpm instal electron

1.4 修改package.json文件

将package.json文件中修改两处。

首先是把main的值修改为main.js。

然后是在scripts里添加一个"start":"electron ." 用来启动项目。

二、编写加载音乐文件

2.1 创建主窗体

在根目录下创建一个main.js文件。

main.js整体代码 

  1. const { app, BrowserWindow, ipcMain } = require('electron');
  2. const path = require('path');
  3. let mainWindow;
  4. function createWindow() {
  5. // 创建浏览器窗口
  6. mainWindow = new BrowserWindow({
  7. width: 800,
  8. height: 600,
  9. webPreferences: {
  10. nodeIntegration: true, // 允许在渲染进程中使用 Node.js API
  11. preload: path.join(__dirname, 'preload.js') // 使用 preload 脚本
  12. },
  13. });
  14. // 加载应用的 index.html 文件
  15. mainWindow.loadFile('app/index.html');
  16. // 监听窗口关闭事件
  17. mainWindow.on('closed', () => {
  18. mainWindow = null;
  19. });
  20. }
  21. // 当 Electron 完成初始化并准备创建浏览器窗口时调用 createWindow 函数
  22. app.whenReady().then(createWindow);
  23. // 监听所有窗口关闭事件
  24. app.on('window-all-closed', () => {
  25. if (process.platform !== 'darwin') {
  26. app.quit(); // 关闭应用
  27. }
  28. });
  29. // 在激活应用时创建一个新窗口
  30. app.on('activate', () => {
  31. if (BrowserWindow.getAllWindows().length === 0) {
  32. createWindow();
  33. }
  34. });
  35. // 监听渲染进程发送的消息
  36. ipcMain.on('selected-file', (event, filePath) => {
  37. console.log('Selected file:', filePath);
  38. });

2.2 创建 preload脚本

因为无法再自定义js中使用require所以,通过使用 preload 脚本,可以在渲染进程中直接访问 Node.js 的模块和 Electron 的 API。

在根目录下创建一个名为 preload.js的脚本文件:

  1. const { contextBridge, ipcRenderer } = require('electron');
  2. // 向渲染进程暴露的 API
  3. const api = {
  4. sendSelectedFilePath: (filePath) => {
  5. ipcRenderer.send('selected-file', filePath);
  6. },
  7. };
  8. // 将 API 注入到 window 对象中,使其在渲染进程中可用
  9. contextBridge.exposeInMainWorld('api', api);

 三、编写前端代码

3.1 创建index.html

在根目录下创建一个app目录,在目录中创建一个index.html文件

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8" />
  5. <title>香菜的开发日记-播放器</title>
  6. <style>
  7. /* 样式表 */
  8. body {
  9. font-family: Arial, sans-serif;
  10. background-color: #000000;
  11. text-align: center;
  12. }
  13. .player-container {
  14. background-color: #1d1d1d;
  15. border-radius: 8px;
  16. padding: 20px;
  17. box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
  18. width: 400px;
  19. margin: 0 auto;
  20. }
  21. .nav-bar {
  22. display: flex;
  23. justify-content: space-between;
  24. }
  25. #music-name {
  26. color: #ffffff;
  27. font-size: 24px;
  28. text-align: left;
  29. }
  30. label {
  31. background-color: #848494;
  32. color: #fff;
  33. padding: 5px;
  34. border-radius: 4px;
  35. cursor: pointer;
  36. display: inline-block;
  37. margin-bottom: 20px;
  38. transition: background-color 0.3s ease;
  39. }
  40. label:hover {
  41. background-color: #1565c0;
  42. }
  43. /* 音乐开始时间和结束时间代码块 */
  44. .time {
  45. display: flex;
  46. justify-content: space-between;
  47. margin-top: 10px;
  48. }
  49. .time span {
  50. color: #8c8b9c;
  51. font-size: 14px;
  52. }
  53. .option span {
  54. font-size: 35px;
  55. margin-right: 15px;
  56. }
  57. .option span:hover {
  58. cursor: pointer;
  59. }
  60. .audio-player {
  61. width: 100%;
  62. margin-top: 20px;
  63. display: none; /* 初始不显示 */
  64. }
  65. .progress-bar {
  66. position: relative;
  67. width: 100%;
  68. height: 10px;
  69. background-color: #4b4b5a;
  70. border-radius: 5px;
  71. margin-top: 20px;
  72. }
  73. .progress-bar .progress {
  74. position: absolute;
  75. top: 0;
  76. left: 0;
  77. height: 100%;
  78. background-color: #ffffff;
  79. border-radius: 5px;
  80. }
  81. </style>
  82. </head>
  83. <body>
  84. <!-- 音乐播放器界面 -->
  85. <div class="player-container">
  86. <div class="nav-bar">
  87. <div id="music-name"></div> <!-- 音乐名字 -->
  88. <div class="music-option">
  89. <label for="file-input">选择音乐</label> <!-- 文件选择器标签 -->
  90. <input
  91. type="file"
  92. id="file-input"
  93. accept=".mp3"
  94. style="display: none" <!-- 不显示选择器 -->
  95. />
  96. </div>
  97. </div>
  98. <div class="progress-bar">
  99. <div class="progress"></div>
  100. </div>
  101. <div class="time">
  102. <span class="current-time">00:00</span> <!-- 当前时间 -->
  103. <span class="duration">00:00</span> <!-- 总时长 -->
  104. </div>
  105. <div class="option">
  106. <span id="play-button">▶️</span> <!-- 播放按钮 -->
  107. </div>
  108. <audio
  109. id="audio-player"
  110. class="audio-player"
  111. preload="auto"
  112. controls
  113. ></audio>
  114. </div>
  115. <script src="render.js"></script> <!-- 引入渲染脚本 -->
  116. </body>
  117. </html>

3.2 创建render.js

在app目录下创建一个render.js文件。

这js文件主要是对打开mp3音乐文件操作,播放、暂停按钮的时间监听功能。

  1. // 监听页面加载完成事件
  2. window.addEventListener("DOMContentLoaded", () => {
  3. // 获取页面上的元素
  4. const fileInput = document.getElementById("file-input"); // 文件选择器
  5. const playButton = document.getElementById("play-button"); // 播放按钮
  6. const audioPlayer = document.getElementById("audio-player"); // 音频播放器
  7. const musicName = document.getElementById("music-name"); // 音乐名字元素
  8. const currentTimeElement = document.querySelector(".current-time"); // 当前时间元素
  9. const durationElement = document.querySelector(".duration"); // 总时长元素
  10. const progressElement = document.querySelector(".progress"); // 进度条元素
  11. var play = false; // 播放状态,默认为暂停
  12. // 监听选择文件事件
  13. fileInput.addEventListener("change", (event) => {
  14. const file = event.target.files[0];
  15. const filePath = URL.createObjectURL(file); // 获取文件路径
  16. const fileName = file.name.split(".")[0]; // 获取文件名(不包含扩展名)
  17. musicName.innerText = fileName; // 设置音乐名字
  18. audioPlayer.src = filePath; // 设置音频播放器的源
  19. audioPlayer.load(); // 加载音频
  20. play = true; // 设置播放状态为播放
  21. // 调用预加载脚本中的方法,发送文件路径给主进程
  22. window.api.sendSelectedFilePath(filePath);
  23. });
  24. // 监听播放按钮点击事件
  25. playButton.addEventListener("click", () => {
  26. if (play) {
  27. audioPlayer.play(); // 播放音乐
  28. playButton.innerText = "⏸"; // 修改播放按钮文本为暂停符号
  29. play = false; // 设置播放状态为暂停
  30. } else {
  31. audioPlayer.pause(); // 暂停音乐
  32. playButton.innerText = "▶️"; // 修改播放按钮文本为播放符号
  33. play = true; // 设置播放状态为播放
  34. }
  35. });
  36. // 监听音频元数据加载完成事件
  37. audioPlayer.addEventListener("loadedmetadata", () => {
  38. const duration = formatTime(audioPlayer.duration); // 格式化总时长
  39. durationElement.textContent = duration; // 更新总时长元素的文本
  40. });
  41. // 监听音频播放时间更新事件
  42. audioPlayer.addEventListener("timeupdate", () => {
  43. const currentTime = formatTime(audioPlayer.currentTime); // 格式化当前时间
  44. currentTimeElement.textContent = currentTime; // 更新当前时间元素的文本
  45. const progress = (audioPlayer.currentTime / audioPlayer.duration) * 100; // 计算进度百分比
  46. progressElement.style.width = `${progress}%`; // 更新进度条的宽度
  47. });
  48. });
  49. /**
  50. * 格式化时间函数
  51. * @param {number} time - 时间,以秒为单位
  52. * @returns {string} 格式化后的时间,格式为:mm:ss
  53. */
  54. function formatTime(time) {
  55. const minutes = Math.floor(time / 60); // 分钟数
  56. const seconds = Math.floor(time % 60); // 秒数
  57. return `${padZero(minutes)}:${padZero(seconds)}`; // 返回格式化后的时间字符串
  58. }
  59. /**
  60. * 在数字前面补零函数
  61. * @param {number} number - 数字
  62. * @returns {string} 补零后的字符串
  63. */
  64. function padZero(number) {
  65. return number.toString().padStart(2, "0"); // 将数字转换为字符串,并在前面补零
  66. }

3.3 目录结构

具体的目录结构如下:

四、运行代码

4.1 运行代码

在终端命令行中输入

npm start 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/998947
推荐阅读
  

闽ICP备14008679号