使用 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整体代码 

const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');

let mainWindow;

function createWindow() {
  // 创建浏览器窗口
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true, // 允许在渲染进程中使用 Node.js API
      preload: path.join(__dirname, 'preload.js') // 使用 preload 脚本
    },
  });

  // 加载应用的 index.html 文件
  mainWindow.loadFile('app/index.html');

  // 监听窗口关闭事件
  mainWindow.on('closed', () => {
    mainWindow = null;
  });
}

// 当 Electron 完成初始化并准备创建浏览器窗口时调用 createWindow 函数
app.whenReady().then(createWindow);

// 监听所有窗口关闭事件
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit(); // 关闭应用
  }
});

// 在激活应用时创建一个新窗口
app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow();
  }
});

// 监听渲染进程发送的消息
ipcMain.on('selected-file', (event, filePath) => {
  console.log('Selected file:', filePath);
});

2.2 创建 preload脚本

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

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

const { contextBridge, ipcRenderer } = require('electron');

// 向渲染进程暴露的 API
const api = {
  sendSelectedFilePath: (filePath) => {
    ipcRenderer.send('selected-file', filePath);
  },
};

// 将 API 注入到 window 对象中,使其在渲染进程中可用
contextBridge.exposeInMainWorld('api', api);

 三、编写前端代码

3.1 创建index.html

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

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>香菜的开发日记-播放器</title>
    <style>
      /* 样式表 */
      body {
        font-family: Arial, sans-serif;
        background-color: #000000;
        text-align: center;
      }

      .player-container {
        background-color: #1d1d1d;
        border-radius: 8px;
        padding: 20px;
        box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
        width: 400px;
        margin: 0 auto;
      }

      .nav-bar {
        display: flex;
        justify-content: space-between;
      }

      #music-name {
        color: #ffffff;
        font-size: 24px;
        text-align: left;
      }

      label {
        background-color: #848494;
        color: #fff;
        padding: 5px;
        border-radius: 4px;
        cursor: pointer;
        display: inline-block;
        margin-bottom: 20px;
        transition: background-color 0.3s ease;
      }

      label:hover {
        background-color: #1565c0;
      }

      /* 音乐开始时间和结束时间代码块 */
      .time {
        display: flex;
        justify-content: space-between;
        margin-top: 10px;
      }

      .time span {
        color: #8c8b9c;
        font-size: 14px;
      }

      .option span {
        font-size: 35px;
        margin-right: 15px;
      }

      .option span:hover {
        cursor: pointer;
      }
    
      .audio-player {
        width: 100%;
        margin-top: 20px;
        display: none; /* 初始不显示 */
      }

      .progress-bar {
        position: relative;
        width: 100%;
        height: 10px;
        background-color: #4b4b5a;
        border-radius: 5px;
        margin-top: 20px;
      }

      .progress-bar .progress {
        position: absolute;
        top: 0;
        left: 0;
        height: 100%;
        background-color: #ffffff;
        border-radius: 5px;
      }
      
    </style>
  </head>
  <body>
    <!-- 音乐播放器界面 -->
    <div class="player-container">
      <div class="nav-bar">
        <div id="music-name"></div> <!-- 音乐名字 -->
        <div class="music-option">
          <label for="file-input">选择音乐</label> <!-- 文件选择器标签 -->
          <input
            type="file"
            id="file-input"
            accept=".mp3"
            style="display: none" <!-- 不显示选择器 -->
          />
        </div>
      </div>
      <div class="progress-bar">
        <div class="progress"></div>
      </div>
      <div class="time">
        <span class="current-time">00:00</span> <!-- 当前时间 -->
        <span class="duration">00:00</span> <!-- 总时长 -->
      </div>
      <div class="option">
        <span id="play-button">▶️</span> <!-- 播放按钮 -->
      </div>
      <audio
        id="audio-player"
        class="audio-player"
        preload="auto" 
        controls
      ></audio>
    </div>

    <script src="render.js"></script> <!-- 引入渲染脚本 -->
  </body>
</html>

3.2 创建render.js

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

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

// 监听页面加载完成事件
window.addEventListener("DOMContentLoaded", () => {
  // 获取页面上的元素
  const fileInput = document.getElementById("file-input"); // 文件选择器
  const playButton = document.getElementById("play-button"); // 播放按钮
  const audioPlayer = document.getElementById("audio-player"); // 音频播放器
  const musicName = document.getElementById("music-name"); // 音乐名字元素
  const currentTimeElement = document.querySelector(".current-time"); // 当前时间元素
  const durationElement = document.querySelector(".duration"); // 总时长元素
  const progressElement = document.querySelector(".progress"); // 进度条元素

  var play = false; // 播放状态,默认为暂停

  // 监听选择文件事件
  fileInput.addEventListener("change", (event) => {
    const file = event.target.files[0];
    const filePath = URL.createObjectURL(file); // 获取文件路径
    const fileName = file.name.split(".")[0]; // 获取文件名(不包含扩展名)

    musicName.innerText = fileName; // 设置音乐名字
    audioPlayer.src = filePath; // 设置音频播放器的源
    audioPlayer.load(); // 加载音频
    play = true; // 设置播放状态为播放

    // 调用预加载脚本中的方法,发送文件路径给主进程
    window.api.sendSelectedFilePath(filePath);
  });

  // 监听播放按钮点击事件
  playButton.addEventListener("click", () => {
    if (play) {
      audioPlayer.play(); // 播放音乐
      playButton.innerText = "⏸"; // 修改播放按钮文本为暂停符号
      play = false; // 设置播放状态为暂停
    } else {
      audioPlayer.pause(); // 暂停音乐
      playButton.innerText = "▶️"; // 修改播放按钮文本为播放符号
      play = true; // 设置播放状态为播放
    }
  });

  // 监听音频元数据加载完成事件
  audioPlayer.addEventListener("loadedmetadata", () => {
    const duration = formatTime(audioPlayer.duration); // 格式化总时长
    durationElement.textContent = duration; // 更新总时长元素的文本
  });
  
  // 监听音频播放时间更新事件
  audioPlayer.addEventListener("timeupdate", () => {
    const currentTime = formatTime(audioPlayer.currentTime); // 格式化当前时间
    currentTimeElement.textContent = currentTime; // 更新当前时间元素的文本

    const progress = (audioPlayer.currentTime / audioPlayer.duration) * 100; // 计算进度百分比
    progressElement.style.width = `${progress}%`; // 更新进度条的宽度
  });
});

/**
 * 格式化时间函数
 * @param {number} time - 时间,以秒为单位
 * @returns {string} 格式化后的时间,格式为:mm:ss
 */
function formatTime(time) {
  const minutes = Math.floor(time / 60); // 分钟数
  const seconds = Math.floor(time % 60); // 秒数
  return `${padZero(minutes)}:${padZero(seconds)}`; // 返回格式化后的时间字符串
}

/**
 * 在数字前面补零函数
 * @param {number} number - 数字
 * @returns {string} 补零后的字符串
 */
function padZero(number) {
  return number.toString().padStart(2, "0"); // 将数字转换为字符串,并在前面补零
}

3.3 目录结构

具体的目录结构如下:

四、运行代码

4.1 运行代码

在终端命令行中输入

npm start 

 

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

香菜的开发日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值