Electron+vue打造一个本地播放器(附项目代码)(1)

function streamToBlob (stream, mimeType) {

if (mimeType != null && typeof mimeType !== ‘string’) {

throw new Error(‘Invalid mimetype, expected string.’)

}

return new Promise((resolve, reject) => {

const chunks = []

stream

.on(‘data’, chunk => chunks.push(chunk))

.once(‘end’, () => {

const blob = mimeType != null

? new Blob(chunks, { type: mimeType })

: new Blob(chunks)

resolve(blob)

})

.once(‘error’, reject)

})

}

转blob

let fileUrl; // blob对象

streamToBlob(stream)

.then(res => {

fileUrl = res;

// console.log(fileUrl);

//将blob对象转成blob链接

let filePath = window.URL.createObjectURL(fileUrl);

// console.log(filePath);

this.wavesurfer.load(filePath);

// 自动播放

this.wavesurfer.play();

this.playing = true;

})

.catch(err => {

console.log(err);

});

这样就实现了加载本地文件播放了

上一首下一首功能

这里的上一首下一首的功能是基于上面获取到的文件的绝对路径,通过node的path模块,path.dirname获取到文件的父级目录。

const dirPath = path.dirname(diskPath);

然后通过fs.readdir读取目录下所有文件,会返回一个文件名数组,找到该目录下正在播放的文件的下标,通过数组下标判断前一首和后一首歌曲的名称,然后再组装成绝对路径,读取资源播放

playFileList(diskPath, pos) {

let isInFiles;

let fileIndex;

let preIndex;

let nextIndex;

let fullPath;

let dirPath = path.dirname(diskPath);

let basename = path.basename(diskPath);

fs.readdir(dirPath, (err, files) => {

isInFiles = files.includes(basename);

if (isInFiles && pos === “pre”) {

fileIndex = files.indexOf(basename);

preIndex = fileIndex - 1;

fullPath = path.resolve(dirPath, files[preIndex]);

this.loadMusic(fullPath);

}

if (isInFiles && pos === “next”) {

fileIndex = files.indexOf(basename);

nextIndex = fileIndex + 1;

fullPath = path.resolve(dirPath, files[nextIndex]);

this.loadMusic(fullPath);

}

});

},

声音音量控制

音量控制需要通过监听input的键入事件,获取到range的值,然后通过设置样式background-image,动态计算百分比,然后调用wavesurfer的setVolume方法调节音量

:style=“background-image:linear-gradient( to right, ${fillColor}, ${fillColor} ${percent}, ${emptyColor} ${percent})

改变音量changeVol事件

changeVol(e) {

let val = e.target.value;

let min = e.target.min;

let max = e.target.max;

let rate = (val - min) / (max - min);

this.percent = 100 * rate + “%”;

console.log(this.percent, rate);

this.wavesurfer.setVolume(Number(rate));

},

自定义标题栏

个人觉得系统自带的菜单栏太丑了,就给设置了无边框再自己加上最小化,关闭的功能。最小化,关闭是通过ipc通信,渲染进程监听到有点击操作后,通知主进程进行相应的操作。

渲染进程

close() {

ipcRenderer.send(“close”);

},

minimize() {

ipcRenderer.send(“minimize”);

}

主进程

ipcMain.on(“close”, () => {

win.close();

app.quit();

});

ipcMain.on(“minimize”, () => {

win.minimize();

});

打开多个实例的问题

在实际测试的过程中发现会出现,打开一首新的音乐播放,就会出现重新开一个实例的现象,不能实现覆盖播放,后面查阅资料发现electron有一个second-instance事件,可以监听是否打开了第二个实例。当第二个实例被执行并且调用 app.requestSingleInstanceLock()") 时,这个事件将在应用程序的首个实例中触发,并且会返回第二个实例的相关信息,然后通过主进程通知渲染进程,告知渲染进程第二个实例的本地绝对路径,渲染进程接收到信息后,立马加载第二个实例的资源。app.requestSingleInstanceLock(),表示应用程序实例是否成功取得了锁。如果它取得锁失败,可以假设另一个应用实例已经取得了锁并且仍旧在运行,所以可以直接关闭掉,这样就避免了打开多个实例的问题

主进程

const gotTheLock = app.requestSingleInstanceLock();

if (gotTheLock) {

app.on(“second-instance”, (event, commandLine, workingDirectory) => {

// 监听是否有第二个实例,向渲染进程发送第二个实例的本地路径

win.webContents.send(“path”, ${commandLine[commandLine.length - 1]});

if (win) {

if (win.isMinimized()) win.restore();

win.focus();

}

});

app.on(“ready”, async () => {

createWindow();

});

} else {

app.quit();

}

渲染进程

ipcRenderer.on(“path”, (event, arg) => {

const newOriginPath = arg;

// console.log(newOriginPath);

this.loadMusic(newOriginPath);

});

自动更新

需求的起因是,在很兴奋的给女朋友成品的时候,尴尬的被女朋友试出很多bug(捂脸ing),然后频繁的修改打包,然后通过私发传给她。特别麻烦,所以这个需求很急迫。最后查了资料,通过electron-updater实现了这个需求.

安装electron-updater

yarn add electron-updater

发布设置

electronBuilder: {

builderOptions: {

publish: [‘github’]

}

}

主进程监听

autoUpdater.on(“checking-for-update”, () => {});

autoUpdater.on(“update-available”, info => {

dialog.showMessageBox({

title: “新版本发布”,

message: “有新内容更新,稍后将重新为您安装”,

buttons: [“确定”],

type: “info”,

noLink: true

});

});

autoUpdater.on(“update-downloaded”, info => {

autoUpdater.quitAndInstall();

});

生成Github Access Token 因为是用github作为更新站,所以本地需要相应的操作权限,去这里生成token,戳这,生成后,在powershell中设置

# 例如 Environment::SetEnvironmentVariable(“GH_TOKEN”,“sdfdsfgsdg14463232”,“User”)

打包上传Github

yarn electron:build -p always

最后

四轮技术面+一轮hr面结束,学习到了不少,面试也是一个学习检测自己的过程,面试前大概复习了 一周的时间,把以前的代码看了一下,字节跳动比较注重算法,面试前刷了下leetcode和剑指offer, 也刷了些在牛客网上的面经。大概就说这些了,写代码去了~

祝大家都能收获大厂offer~

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

篇幅有限,仅展示部分内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值