mirror of
https://github.com/imsyy/SPlayer.git
synced 2025-11-25 03:14:57 +08:00
🌈 style: 优化桌面歌词样式
This commit is contained in:
@@ -62,9 +62,14 @@ const initLyricIpc = (): void => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 更新歌词窗口配置
|
// 更新歌词窗口配置
|
||||||
ipcMain.on("update-desktop-lyric-option", (_, option) => {
|
ipcMain.on("update-desktop-lyric-option", (_, option, callback: boolean = false) => {
|
||||||
if (!option || !isWinAlive(lyricWin)) return;
|
if (!option || !isWinAlive(lyricWin)) return;
|
||||||
lyricWin.webContents.send("desktop-lyric-option-change", option);
|
store.set("lyric.config", option);
|
||||||
|
// 触发窗口更新
|
||||||
|
if (callback && isWinAlive(lyricWin)) {
|
||||||
|
lyricWin.webContents.send("update-desktop-lyric-option", option);
|
||||||
|
}
|
||||||
|
mainWin?.webContents.send("update-desktop-lyric-option", option);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 播放状态更改
|
// 播放状态更改
|
||||||
@@ -132,18 +137,14 @@ const initLyricIpc = (): void => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 获取配置
|
// 获取配置
|
||||||
ipcMain.handle("get-desktop-lyric-option", () => {
|
ipcMain.handle("request-desktop-lyric-option", () => {
|
||||||
return store.get("lyric");
|
const config = store.get("lyric.config");
|
||||||
});
|
console.log(config);
|
||||||
|
|
||||||
// 保存配置
|
if (isWinAlive(lyricWin)) {
|
||||||
ipcMain.on("set-desktop-lyric-option", (_, option, callback: boolean = false) => {
|
lyricWin.webContents.send("update-desktop-lyric-option", config);
|
||||||
store.set("lyric", option);
|
|
||||||
// 触发窗口更新
|
|
||||||
if (callback && isWinAlive(lyricWin)) {
|
|
||||||
lyricWin.webContents.send("desktop-lyric-option-change", option);
|
|
||||||
}
|
}
|
||||||
mainWin?.webContents.send("desktop-lyric-option-change", option);
|
return config;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 发送主程序事件
|
// 发送主程序事件
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { BrowserWindow } from "electron";
|
|||||||
import { createWindow } from "./index";
|
import { createWindow } from "./index";
|
||||||
import { useStore } from "../store";
|
import { useStore } from "../store";
|
||||||
import { lyricWinUrl } from "../utils/config";
|
import { lyricWinUrl } from "../utils/config";
|
||||||
|
import mainWindow from "./main-window";
|
||||||
|
|
||||||
class LyricWindow {
|
class LyricWindow {
|
||||||
private win: BrowserWindow | null = null;
|
private win: BrowserWindow | null = null;
|
||||||
@@ -25,6 +26,11 @@ class LyricWindow {
|
|||||||
store.set("lyric", { ...store.get("lyric"), width, height });
|
store.set("lyric", { ...store.get("lyric"), width, height });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// 歌词窗口关闭
|
||||||
|
this.win?.on("close", () => {
|
||||||
|
const mainWin = mainWindow?.getWin();
|
||||||
|
mainWin?.webContents.send("closeDesktopLyric");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 创建主窗口
|
* 创建主窗口
|
||||||
|
|||||||
@@ -331,6 +331,60 @@
|
|||||||
@update:value="player.toggleDesktopLyric"
|
@update:value="player.toggleDesktopLyric"
|
||||||
/>
|
/>
|
||||||
</n-card>
|
</n-card>
|
||||||
|
<n-card class="set-item">
|
||||||
|
<div class="label">
|
||||||
|
<n-text class="name">锁定桌面歌词位置</n-text>
|
||||||
|
<n-text class="tip" :depth="3">是否锁定桌面歌词位置,防止误触或遮挡内容</n-text>
|
||||||
|
</div>
|
||||||
|
<n-switch
|
||||||
|
v-model:value="desktopLyricConfig.isLock"
|
||||||
|
:round="false"
|
||||||
|
class="set"
|
||||||
|
@update:value="saveDesktopLyricConfig"
|
||||||
|
/>
|
||||||
|
</n-card>
|
||||||
|
<n-card class="set-item">
|
||||||
|
<div class="label">
|
||||||
|
<n-text class="name">双行歌词</n-text>
|
||||||
|
<n-text class="tip" :depth="3">是否启用双行歌词,交替显示当前句和下一句</n-text>
|
||||||
|
</div>
|
||||||
|
<n-switch
|
||||||
|
v-model:value="desktopLyricConfig.isDoubleLine"
|
||||||
|
:round="false"
|
||||||
|
class="set"
|
||||||
|
@update:value="saveDesktopLyricConfig"
|
||||||
|
/>
|
||||||
|
</n-card>
|
||||||
|
<n-card class="set-item">
|
||||||
|
<div class="label">
|
||||||
|
<n-text class="name">限制歌词位置</n-text>
|
||||||
|
<n-text class="tip" :depth="3">是否限制桌面歌词位置在当前屏幕内</n-text>
|
||||||
|
</div>
|
||||||
|
<n-switch
|
||||||
|
v-model:value="desktopLyricConfig.limitBounds"
|
||||||
|
:round="false"
|
||||||
|
class="set"
|
||||||
|
@update:value="saveDesktopLyricConfig"
|
||||||
|
/>
|
||||||
|
</n-card>
|
||||||
|
<!-- position -->
|
||||||
|
<n-card class="set-item">
|
||||||
|
<div class="label">
|
||||||
|
<n-text class="name">对齐方式</n-text>
|
||||||
|
<n-text class="tip" :depth="3">桌面歌词对齐方式</n-text>
|
||||||
|
</div>
|
||||||
|
<n-select
|
||||||
|
v-model:value="desktopLyricConfig.position"
|
||||||
|
:options="[
|
||||||
|
{ label: '左对齐', value: 'left' },
|
||||||
|
{ label: '居中对齐', value: 'center' },
|
||||||
|
{ label: '右对齐', value: 'right' },
|
||||||
|
{ label: '左右分离', value: 'both' },
|
||||||
|
]"
|
||||||
|
class="set"
|
||||||
|
@update:value="saveDesktopLyricConfig"
|
||||||
|
/>
|
||||||
|
</n-card>
|
||||||
<n-card class="set-item">
|
<n-card class="set-item">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<n-text class="name">桌面歌词文字大小</n-text>
|
<n-text class="name">桌面歌词文字大小</n-text>
|
||||||
@@ -352,11 +406,24 @@
|
|||||||
</n-card>
|
</n-card>
|
||||||
<n-card class="set-item">
|
<n-card class="set-item">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<n-text class="name">主题色</n-text>
|
<n-text class="name">已播放文字</n-text>
|
||||||
<n-text class="tip" :depth="3">桌面歌词文字主色</n-text>
|
<n-text class="tip" :depth="3">桌面歌词已播放文字颜色</n-text>
|
||||||
</div>
|
</div>
|
||||||
<n-color-picker
|
<n-color-picker
|
||||||
v-model:value="desktopLyricConfig.mainColor"
|
v-model:value="desktopLyricConfig.playedColor"
|
||||||
|
:show-alpha="false"
|
||||||
|
:modes="['hex']"
|
||||||
|
class="set"
|
||||||
|
@complete="saveDesktopLyricConfig"
|
||||||
|
/>
|
||||||
|
</n-card>
|
||||||
|
<n-card class="set-item">
|
||||||
|
<div class="label">
|
||||||
|
<n-text class="name">未播放文字</n-text>
|
||||||
|
<n-text class="tip" :depth="3">桌面歌词未播放文字颜色</n-text>
|
||||||
|
</div>
|
||||||
|
<n-color-picker
|
||||||
|
v-model:value="desktopLyricConfig.unplayedColor"
|
||||||
:show-alpha="false"
|
:show-alpha="false"
|
||||||
:modes="['hex']"
|
:modes="['hex']"
|
||||||
class="set"
|
class="set"
|
||||||
@@ -390,27 +457,34 @@
|
|||||||
import { useSettingStore, useStatusStore } from "@/stores";
|
import { useSettingStore, useStatusStore } from "@/stores";
|
||||||
import { cloneDeep, isEqual } from "lodash-es";
|
import { cloneDeep, isEqual } from "lodash-es";
|
||||||
import { isElectron } from "@/utils/env";
|
import { isElectron } from "@/utils/env";
|
||||||
import player from "@/utils/player";
|
|
||||||
import { openLyricExclude } from "@/utils/modal";
|
import { openLyricExclude } from "@/utils/modal";
|
||||||
|
import player from "@/utils/player";
|
||||||
|
import { LyricConfig } from "@/types/desktop-lyric";
|
||||||
|
|
||||||
const statusStore = useStatusStore();
|
const statusStore = useStatusStore();
|
||||||
const settingStore = useSettingStore();
|
const settingStore = useSettingStore();
|
||||||
|
|
||||||
// 桌面歌词配置
|
// 桌面歌词配置
|
||||||
const defaultDesktopLyricConfig = {
|
const defaultDesktopLyricConfig = {
|
||||||
fontSize: 30,
|
isLock: false,
|
||||||
mainColor: "#fff",
|
playedColor: "#fe7971",
|
||||||
|
unplayedColor: "#ccc",
|
||||||
shadowColor: "rgba(0, 0, 0, 0.5)",
|
shadowColor: "rgba(0, 0, 0, 0.5)",
|
||||||
};
|
fontFamily: "system-ui",
|
||||||
const desktopLyricConfig = reactive({ ...defaultDesktopLyricConfig });
|
fontSize: 24,
|
||||||
|
isDoubleLine: true,
|
||||||
|
position: "both",
|
||||||
|
limitBounds: false,
|
||||||
|
} as LyricConfig;
|
||||||
|
const desktopLyricConfig = reactive<LyricConfig>({ ...defaultDesktopLyricConfig });
|
||||||
|
|
||||||
// 获取桌面歌词配置
|
// 获取桌面歌词配置
|
||||||
const getDesktopLyricConfig = async () => {
|
const getDesktopLyricConfig = async () => {
|
||||||
if (!isElectron) return;
|
if (!isElectron) return;
|
||||||
const config = await window.electron.ipcRenderer.invoke("get-desktop-lyric-option");
|
const config = await window.electron.ipcRenderer.invoke("request-desktop-lyric-option");
|
||||||
if (config) Object.assign(desktopLyricConfig, config);
|
if (config) Object.assign(desktopLyricConfig, config);
|
||||||
// 监听更新
|
// 监听更新
|
||||||
window.electron.ipcRenderer.on("desktop-lyric-option-change", (_, config) => {
|
window.electron.ipcRenderer.on("update-desktop-lyric-option", (_, config) => {
|
||||||
if (config && !isEqual(desktopLyricConfig, config)) {
|
if (config && !isEqual(desktopLyricConfig, config)) {
|
||||||
Object.assign(desktopLyricConfig, config);
|
Object.assign(desktopLyricConfig, config);
|
||||||
}
|
}
|
||||||
@@ -423,7 +497,7 @@ const saveDesktopLyricConfig = () => {
|
|||||||
if (!isElectron) return;
|
if (!isElectron) return;
|
||||||
console.log(cloneDeep(desktopLyricConfig));
|
console.log(cloneDeep(desktopLyricConfig));
|
||||||
window.electron.ipcRenderer.send(
|
window.electron.ipcRenderer.send(
|
||||||
"set-desktop-lyric-option",
|
"update-desktop-lyric-option",
|
||||||
cloneDeep(desktopLyricConfig),
|
cloneDeep(desktopLyricConfig),
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
@@ -439,7 +513,11 @@ const saveDesktopLyricConfig = () => {
|
|||||||
const restoreDesktopLyricConfig = () => {
|
const restoreDesktopLyricConfig = () => {
|
||||||
try {
|
try {
|
||||||
if (!isElectron) return;
|
if (!isElectron) return;
|
||||||
window.electron.ipcRenderer.send("set-desktop-lyric-option", defaultDesktopLyricConfig, true);
|
window.electron.ipcRenderer.send(
|
||||||
|
"update-desktop-lyric-option",
|
||||||
|
defaultDesktopLyricConfig,
|
||||||
|
true,
|
||||||
|
);
|
||||||
window.$message.success("桌面歌词配置已恢复默认");
|
window.$message.success("桌面歌词配置已恢复默认");
|
||||||
console.log(defaultDesktopLyricConfig, desktopLyricConfig);
|
console.log(defaultDesktopLyricConfig, desktopLyricConfig);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
6
src/types/desktop-lyric.d.ts
vendored
6
src/types/desktop-lyric.d.ts
vendored
@@ -23,10 +23,8 @@ export interface LyricConfig {
|
|||||||
playedColor: string;
|
playedColor: string;
|
||||||
/** 未播放颜色 */
|
/** 未播放颜色 */
|
||||||
unplayedColor: string;
|
unplayedColor: string;
|
||||||
/** 描边 */
|
/** 阴影颜色 */
|
||||||
stroke: string;
|
shadowColor: string;
|
||||||
/** 描边宽度 */
|
|
||||||
strokeWidth: number;
|
|
||||||
/** 字体 */
|
/** 字体 */
|
||||||
fontFamily: string;
|
fontFamily: string;
|
||||||
/** 字体大小 */
|
/** 字体大小 */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<n-config-provider :theme="null">
|
<n-config-provider :theme="null">
|
||||||
<div
|
<div
|
||||||
ref="desktopLyricsRef"
|
ref="desktopLyricRef"
|
||||||
:class="[
|
:class="[
|
||||||
'desktop-lyric',
|
'desktop-lyric',
|
||||||
{
|
{
|
||||||
@@ -23,17 +23,17 @@
|
|||||||
<span class="song-name">{{ lyricData.playName }}</span>
|
<span class="song-name">{{ lyricData.playName }}</span>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
<n-flex :wrap="false" align="center" justify="center" size="small" @pointerdown.stop>
|
<n-flex :wrap="false" align="center" justify="center" size="small" @pointerdown.stop>
|
||||||
<div class="menu-btn" title="上一曲" @click.stop="sendToMain('playPrev')">
|
<div class="menu-btn" title="上一曲" @click.stop="sendToMainWin('playPrev')">
|
||||||
<SvgIcon name="SkipPrev" />
|
<SvgIcon name="SkipPrev" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="menu-btn"
|
class="menu-btn"
|
||||||
:title="lyricData.playStatus ? '暂停' : '播放'"
|
:title="lyricData.playStatus ? '暂停' : '播放'"
|
||||||
@click.stop="sendToMain('playOrPause')"
|
@click.stop="sendToMainWin('playOrPause')"
|
||||||
>
|
>
|
||||||
<SvgIcon :name="lyricData.playStatus ? 'Pause' : 'Play'" />
|
<SvgIcon :name="lyricData.playStatus ? 'Pause' : 'Play'" />
|
||||||
</div>
|
</div>
|
||||||
<div class="menu-btn" title="下一曲" @click.stop="sendToMain('playNext')">
|
<div class="menu-btn" title="下一曲" @click.stop="sendToMainWin('playNext')">
|
||||||
<SvgIcon name="SkipNext" />
|
<SvgIcon name="SkipNext" />
|
||||||
</div>
|
</div>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
<div class="menu-btn" title="解锁">
|
<div class="menu-btn" title="解锁">
|
||||||
<SvgIcon name="LockOpen" />
|
<SvgIcon name="LockOpen" />
|
||||||
</div>
|
</div>
|
||||||
<div class="menu-btn" title="关闭">
|
<div class="menu-btn" title="关闭" @click.stop="sendToMain('closeDesktopLyric')">
|
||||||
<SvgIcon name="Close" />
|
<SvgIcon name="Close" />
|
||||||
</div>
|
</div>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
@@ -53,6 +53,7 @@
|
|||||||
:style="{
|
:style="{
|
||||||
fontSize: lyricConfig.fontSize + 'px',
|
fontSize: lyricConfig.fontSize + 'px',
|
||||||
fontFamily: lyricConfig.fontFamily,
|
fontFamily: lyricConfig.fontFamily,
|
||||||
|
textShadow: `0 0 4px ${lyricConfig.shadowColor}`,
|
||||||
}"
|
}"
|
||||||
:class="['lyric-container', lyricConfig.position]"
|
:class="['lyric-container', lyricConfig.position]"
|
||||||
vertical
|
vertical
|
||||||
@@ -67,6 +68,10 @@
|
|||||||
>
|
>
|
||||||
{{ line.text }}
|
{{ line.text }}
|
||||||
</span>
|
</span>
|
||||||
|
<!-- 占位 -->
|
||||||
|
<span v-if="lyricConfig.isDoubleLine && renderLyricLines.length === 1" class="lyric-line">
|
||||||
|
|
||||||
|
</span>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
</div>
|
</div>
|
||||||
</n-config-provider>
|
</n-config-provider>
|
||||||
@@ -91,8 +96,7 @@ const lyricConfig = reactive<LyricConfig>({
|
|||||||
isLock: false,
|
isLock: false,
|
||||||
playedColor: "#fe7971",
|
playedColor: "#fe7971",
|
||||||
unplayedColor: "#ccc",
|
unplayedColor: "#ccc",
|
||||||
stroke: "#000",
|
shadowColor: "rgba(0, 0, 0, 0.5)",
|
||||||
strokeWidth: 2,
|
|
||||||
fontFamily: "system-ui",
|
fontFamily: "system-ui",
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
isDoubleLine: true,
|
isDoubleLine: true,
|
||||||
@@ -101,7 +105,7 @@ const lyricConfig = reactive<LyricConfig>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 桌面歌词元素
|
// 桌面歌词元素
|
||||||
const desktopLyricsRef = useTemplateRef<HTMLElement>("desktopLyricsRef");
|
const desktopLyricRef = ref<HTMLElement>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渲染的歌词行
|
* 渲染的歌词行
|
||||||
@@ -207,7 +211,7 @@ const lyricDragMove = async (_position: Position, event: PointerEvent) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 监听桌面歌词拖动
|
// 监听桌面歌词拖动
|
||||||
useDraggable(desktopLyricsRef, {
|
useDraggable(desktopLyricRef, {
|
||||||
onStart: (position, event) => {
|
onStart: (position, event) => {
|
||||||
lyricDragStart(position, event);
|
lyricDragStart(position, event);
|
||||||
},
|
},
|
||||||
@@ -219,28 +223,27 @@ useDraggable(desktopLyricsRef, {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 发送至主窗口
|
// 发送至主进程
|
||||||
const sendToMain = (eventName: string, ...args: any[]) => {
|
const sendToMain = (eventName: string, ...args: any[]) => {
|
||||||
// 特殊处理
|
window.electron.ipcRenderer.send(eventName, ...args);
|
||||||
if (eventName === "win-show") {
|
|
||||||
window.electron.ipcRenderer.send("win-show");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
window.electron.ipcRenderer.send("send-to-main", eventName, ...args);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理歌词数据
|
// 发送至主窗口
|
||||||
const handleLyricData = (data: LyricData) => {
|
const sendToMainWin = (eventName: string, ...args: any[]) => {
|
||||||
Object.assign(lyricData, data);
|
window.electron.ipcRenderer.send("send-to-main", eventName, ...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 接收歌词数据
|
// 接收歌词数据
|
||||||
window.electron.ipcRenderer.on("update-desktop-lyric-data", (_event, data: LyricData) => {
|
window.electron.ipcRenderer.on("update-desktop-lyric-data", (_event, data: LyricData) => {
|
||||||
handleLyricData(data);
|
Object.assign(lyricData, data);
|
||||||
|
});
|
||||||
|
window.electron.ipcRenderer.on("update-desktop-lyric-option", (_event, config: LyricConfig) => {
|
||||||
|
Object.assign(lyricConfig, config);
|
||||||
});
|
});
|
||||||
// 请求歌词数据及配置
|
// 请求歌词数据及配置
|
||||||
window.electron.ipcRenderer.send("request-desktop-lyric-data");
|
window.electron.ipcRenderer.send("request-desktop-lyric-data");
|
||||||
|
window.electron.ipcRenderer.invoke("request-desktop-lyric-option");
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -254,7 +257,6 @@ onMounted(() => {
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
height: 100%;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition: background-color 0.3s;
|
transition: background-color 0.3s;
|
||||||
cursor: move;
|
cursor: move;
|
||||||
@@ -305,16 +307,29 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
.lyric-container {
|
.lyric-container {
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
|
.lyric-line {
|
||||||
|
// 单行
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
&.center {
|
&.center {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
.lyric-line {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.right {
|
&.right {
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
|
.lyric-line {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.both {
|
&.both {
|
||||||
.lyric-line {
|
.lyric-line {
|
||||||
&:nth-child(2n) {
|
&:nth-child(2n) {
|
||||||
margin-left: auto;
|
text-align: right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user