赶项目有点忙,终于有时间再搞搞自己的东西
使用vue3+vite打包双页面electron打开双窗口实现桌面歌词
看看效果
首先把vue项目打包成多页面项目首先在根目录index.html旁边新建一个lrc.html ,修改一下main.ts入口的连接
<div id="app"></div>
<script type="module" src="/src/page/lrc/main.ts"></script>
page目录下新建一个lrc项目 复制app.vue和main.ts过去
只显示个歌词 直接在app.vue里写 利用进程通信实现歌词同步
<script setup lang="ts">
import { useMusciList, type List } from "@/store/list";
import { lrcInfoApi} from "@/api/music"
import { onMounted, reactive, ref, watch, watchEffect } from "vue";
import useMusicHooks from "@/hook/music";
const {parseLrc} = useMusicHooks();
const store = useMusciList();
let lrcArr = reactive<any>({data:[]});
declare const window :{
ipcRenderer:{
receive:Function,
send:Function,
}
} & Window
onMounted(()=>{
init_(store.list[store.playidx].id)
})
let lrcIdx = 0;
let lrcStr = ref<string>('欢迎使用音乐播放器');
const init_ = (id:number)=>{
lrcInfoApi({
id
}).then((res)=>{
if(res.code==200){
lrcArr.data = parseLrc(res.data);
}
})
}
window.ipcRenderer?.receive('setIdx',(idx:number)=>{
init_(store.list[idx].id)
});
//audio获取currentTime传到主进程 主进程再传到歌词窗口 实时设置显示歌词
window.ipcRenderer?.receive('setNow',(now:number)=>{
for (let i = lrcIdx; i < lrcArr.data.length; i++) {
if(now >= lrcArr.data[i].time && now < lrcArr.data[i].end){
lrcStr.value = lrcArr.data[i].words;
break;
}
}
});
</script>
<template>
<div class="main">
<div class="lrc">{{lrcStr}}</div>
</div>
</template>
<style scoped lang="less">
.main{
width: 1200px;
height: 100px;
-webkit-app-region: drag;
.lrc{
font-size: 42px;
letter-spacing: 2px;
height: 100px;
line-height:100px;
color: #f36e6e;
}
}
</style>
和index.html项目下的一样 可以删除引入不需要的模块
在vite.config.ts里面设置入口文件
export default defineConfig({
//...
build:{
rollupOptions: {
input: {
index: resolve(__dirname , './index.html'),
lrc: resolve(__dirname , './lrc.html'),
},
}
}
})
歌词格式转数组格式
歌词文件格式应该是【时间】 歌词
[ar:G.E.M. 邓紫棋]
[ti:桃花诺]
[00:00.00]桃花诺 (《上古情歌》电视剧片尾曲) - G.E.M. 邓紫棋 (Gem Tang)
[00:03.33]作词:张赢
[00:03.72]作曲:罗锟
[00:04.12]编曲:罗锟/Xueran Chen
...
目标数据 id是我在小程序使用scroll-view得scroll-into-view让歌词自动翻滚用的
[{time: 0, id: '0', words: '桃花诺 (《上古情歌》电视剧片尾曲) - G.E.M. 邓紫棋 (Gem Tang)', end: 3.33}
{time: 3.33, id: '3_33', words: '作词:张赢', end: 3.72}
{time: 3.72, id: '3_72', words: '作曲:罗锟', end: 4.12}
{time: 4.12, id: '4_12', words: '编曲:罗锟/Xueran Chen', end: 5.46}
{time: 5.46, id: '5_46', words: '制作人(美国):Xueran Chen', end: 6.97}
{time: 6.97, id: '6_97', words: '制作人(中国):张赢', end: 7.77}]
function parseLrc(lrc:string) {
lrc = lrc.replace(/\r\n/g,"\n");
var lines = lrc.split("\n");
var result = [];
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
var parts = line.split("]")
let time = parseTime(parts[0].substring(1));
if(!isNaN(time)){//去掉空行
let id = (time+'').replace(/\./g,"_");
var obj = {
time: time,
id,
words: parts[1],
end: 0
}
result.push(obj)
if(result[result.length-2]){
result[result.length-2].end = obj.time;
}
}
}
result[result.length-1].end = result[result.length-1].time+20;
return result
}
function parseTime(timeStr:string) {
var time = timeStr.split(":")
return +time[0] * 60 + +time[1]
}
在electron主进程托盘菜单点击打开桌面歌词时新建窗口,如果已经有窗口就关闭窗口
{ label: '打开桌面歌词', click:()=>{openLrc();} },
let lrcWin = null;
const openLrc = ()=>{
if(lrcWin){
lrcWin.destroy();
lrcWin = null;
return;
}
lrcWin = new BrowserWindow({
width: 1200,
height: 100,
minWidth: 1200,
minHeight: 100,
transparent: true,
webPreferences: {
nodeIntegration: true, // 允许在页面中使用节点js
contextIsolation: true, // 启用上下文隔离
enableRemoteModule: true, // 允许使用 remote 模块
preload: path.join(__dirname, "preload.js")
},
frame: false,
});
if (process.env.NODE_ENV == 'development') {
lrcWin.loadURL(`http://localhost:5173/lrc.html`)
} else {
lrcWin.loadFile("dist/lrc.html");
}
let left = Math.floor((width - 1200)/2);
lrcWin.setPosition(left, height-100);
lrcWin.setAlwaysOnTop(true); //歌词窗口总是在最前面 避免被其他窗口挡住
lrcWin.setSkipTaskbar(true); //窗口不显示任务栏图标
}
// 切换歌曲
ipcMain.on('setIdx', (event,idx) => {
if(lrcWin){
lrcWin.webContents.send('setIdx',idx)
}
});
//实时显示歌词
ipcMain.on('setNow', (event,now) => {
if(lrcWin){
lrcWin.webContents.send('setNow',now)
}
});