🐞 fix: 修复桌面歌词字体调节

This commit is contained in:
imsyy
2025-11-06 15:04:40 +08:00
parent a556a2e102
commit 1c9109af73
8 changed files with 206 additions and 77 deletions

View File

@@ -64,6 +64,11 @@ const initLyricIpc = (): void => {
// 更新歌词窗口配置
ipcMain.on("update-desktop-lyric-option", (_, option, callback: boolean = false) => {
if (!option || !isWinAlive(lyricWin)) return;
// 增量更新
const prevOption = store.get("lyric.config");
if (prevOption) {
option = { ...prevOption, ...option };
}
store.set("lyric.config", option);
// 触发窗口更新
if (callback && isWinAlive(lyricWin)) {
@@ -124,9 +129,11 @@ const initLyricIpc = (): void => {
// 更新高度
ipcMain.on("update-window-height", (_, height) => {
if (!isWinAlive(lyricWin)) return;
const store = useStore();
const { width } = lyricWin.getBounds();
// 更新窗口高度
lyricWin.setBounds({ width, height });
store.set("lyric", { ...store.get("lyric"), height });
});
// 请求歌词数据及配置
@@ -139,8 +146,6 @@ const initLyricIpc = (): void => {
// 获取配置
ipcMain.handle("request-desktop-lyric-option", () => {
const config = store.get("lyric.config");
console.log(config);
if (isWinAlive(lyricWin)) {
lyricWin.webContents.send("update-desktop-lyric-option", config);
}

View File

@@ -1,5 +1,7 @@
import { screen } from "electron";
import { storeLog } from "../logger";
import type { LyricConfig } from "../../../src/types/desktop-lyric";
import defaultLyricConfig from "../../../src/assets/data/lyricConfig";
import Store from "electron-store";
storeLog.info("🌱 Store init");
@@ -13,9 +15,6 @@ export interface StoreType {
maximized?: boolean;
};
lyric: {
fontSize: number;
mainColor: string;
shadowColor: string;
// 窗口位置
x?: number;
y?: number;
@@ -32,6 +31,8 @@ export interface StoreType {
* @returns Store<StoreType>
*/
export const useStore = () => {
// 获取主屏幕
const screenData = screen.getPrimaryDisplay();
return new Store<StoreType>({
defaults: {
window: {
@@ -39,25 +40,11 @@ export const useStore = () => {
height: 800,
},
lyric: {
fontSize: 30,
mainColor: "#fff",
shadowColor: "rgba(0, 0, 0, 0.5)",
x: 0,
y: 0,
x: screenData.workAreaSize.width / 2 - 400,
y: screenData.workAreaSize.height - 90,
width: 800,
height: 180,
config: {
isLock: false,
playedColor: "#fe7971",
unplayedColor: "#ccc",
stroke: "#000",
strokeWidth: 2,
fontFamily: "system-ui",
fontSize: 24,
isDoubleLine: true,
position: "both",
limitBounds: false,
},
height: 152,
config: defaultLyricConfig,
},
proxy: "",
},

View File

@@ -43,28 +43,28 @@ class LyricWindow {
width: width || 800,
height: height || 180,
minWidth: 440,
minHeight: 120,
center: !(x && y), // 没有指定位置时居中显示
// maxWidth: 1600,
// maxHeight: 300,
minHeight: 140,
maxWidth: 1600,
maxHeight: 360,
// 没有指定位置时居中显示
center: !(x && y),
// 窗口位置
x,
y,
// transparent: true,
// backgroundColor: "rgba(0, 0, 0, 0)",
transparent: true,
backgroundColor: "rgba(0, 0, 0, 0)",
alwaysOnTop: true,
resizable: true,
movable: true,
show: false,
// 不在任务栏显示
// skipTaskbar: true,
// // 窗口不能最小化
// minimizable: false,
// // 窗口不能最大化
// maximizable: false,
// // 窗口不能进入全屏状态
// fullscreenable: false,
frame: true,
// 窗口不能最小化
minimizable: false,
// 窗口不能最大化
maximizable: false,
// 窗口不能进入全屏状态
fullscreenable: false,
});
if (!this.win) return null;
// 加载地址

View File

@@ -0,0 +1,16 @@
import type { LyricConfig } from "../../types/desktop-lyric";
const config: LyricConfig = {
isLock: false,
playedColor: "#fe7971",
unplayedColor: "#ccc",
shadowColor: "rgba(0, 0, 0, 0.5)",
fontFamily: "system-ui",
fontSize: 24,
fontIsBold: false,
isDoubleLine: true,
position: "both",
limitBounds: false,
};
export default config;

View File

@@ -387,16 +387,58 @@
</n-card>
<n-card class="set-item">
<div class="label">
<n-text class="name">桌面歌词文字大小</n-text>
<n-text class="name">歌词字体</n-text>
<n-text class="tip" :depth="3"> 更改桌面歌词字体 </n-text>
</div>
<n-flex>
<Transition name="fade" mode="out-in">
<n-button
v-if="desktopLyricConfig.fontFamily !== 'system-ui'"
type="primary"
strong
secondary
@click="
() => {
desktopLyricConfig.fontFamily = 'system-ui';
saveDesktopLyricConfig();
}
"
>
恢复默认
</n-button>
</Transition>
<n-select
v-model:value="desktopLyricConfig.fontFamily"
:options="allFontsData"
class="set"
@update:value="saveDesktopLyricConfig"
/>
</n-flex>
</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.fontIsBold"
: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-select
v-model:value="desktopLyricConfig.fontSize"
:options="
Array.from({ length: 41 }, (_, i) => {
Array.from({ length: 96 - 20 + 1 }, (_, i) => {
return {
label: `${10 + i} px`,
value: 10 + i,
label: `${20 + i} px`,
value: 20 + i,
};
})
"
@@ -458,29 +500,22 @@ import { useSettingStore, useStatusStore } from "@/stores";
import { cloneDeep, isEqual } from "lodash-es";
import { isElectron } from "@/utils/env";
import { openLyricExclude } from "@/utils/modal";
import player from "@/utils/player";
import { LyricConfig } from "@/types/desktop-lyric";
import defaultDesktopLyricConfig from "@/assets/data/lyricConfig";
import player from "@/utils/player";
import { SelectOption } from "naive-ui";
const statusStore = useStatusStore();
const settingStore = useSettingStore();
// 全部字体
const allFontsData = ref<SelectOption[]>([]);
// 桌面歌词配置
const defaultDesktopLyricConfig = {
isLock: false,
playedColor: "#fe7971",
unplayedColor: "#ccc",
shadowColor: "rgba(0, 0, 0, 0.5)",
fontFamily: "system-ui",
fontSize: 24,
isDoubleLine: true,
position: "both",
limitBounds: false,
} as LyricConfig;
const desktopLyricConfig = reactive<LyricConfig>({ ...defaultDesktopLyricConfig });
// 获取桌面歌词配置
const getDesktopLyricConfig = async () => {
if (!isElectron) return;
const config = await window.electron.ipcRenderer.invoke("request-desktop-lyric-option");
if (config) Object.assign(desktopLyricConfig, config);
// 监听更新
@@ -527,8 +562,35 @@ const restoreDesktopLyricConfig = () => {
}
};
// 获取全部系统字体
const getAllSystemFonts = async () => {
const allFonts = await window.electron.ipcRenderer.invoke("get-all-fonts");
allFonts.map((v: string) => {
// 去除前后的引号
v = v.replace(/^['"]+|['"]+$/g, "");
allFontsData.value.push({
label: v,
value: v,
style: {
fontFamily: v,
},
});
});
// 添加默认选项
allFontsData.value.unshift({
label: "系统默认",
value: "system-ui",
style: {
fontFamily: "system-ui",
},
});
};
onMounted(() => {
getDesktopLyricConfig();
if (isElectron) {
getDesktopLyricConfig();
getAllSystemFonts();
}
});
</script>

View File

@@ -29,6 +29,8 @@ export interface LyricConfig {
fontFamily: string;
/** 字体大小 */
fontSize: number;
/** 字体是否加粗 */
fontIsBold: boolean;
/** 是否双行 */
isDoubleLine: boolean;
/** 文本排版位置 */

View File

@@ -14,12 +14,6 @@
<div class="menu-btn" title="返回应用" @click.stop="sendToMain('win-show')">
<SvgIcon name="Music" />
</div>
<div class="menu-btn" title="增加字体大小">
<SvgIcon :offset="-1" name="TextSizeAdd" />
</div>
<div class="menu-btn" title="减少字体大小">
<SvgIcon :offset="-1" name="TextSizeReduce" />
</div>
<span class="song-name">{{ lyricData.playName }}</span>
</n-flex>
<n-flex :wrap="false" align="center" justify="center" size="small" @pointerdown.stop>
@@ -38,6 +32,9 @@
</div>
</n-flex>
<n-flex :wrap="false" align="center" justify="flex-end" size="small" @pointerdown.stop>
<div class="menu-btn" title="设置">
<SvgIcon name="Settings" />
</div>
<div class="menu-btn" title="锁定">
<SvgIcon name="Lock" />
</div>
@@ -53,9 +50,12 @@
:style="{
fontSize: lyricConfig.fontSize + 'px',
fontFamily: lyricConfig.fontFamily,
fontWeight: lyricConfig.fontIsBold ? 'bold' : 'normal',
textShadow: `0 0 4px ${lyricConfig.shadowColor}`,
}"
:class="['lyric-container', lyricConfig.position]"
:size="0"
justify="space-around"
vertical
>
<span
@@ -69,9 +69,7 @@
{{ line.text }}
</span>
<!-- 占位 -->
<span v-if="lyricConfig.isDoubleLine && renderLyricLines.length === 1" class="lyric-line">
&nbsp;
</span>
<span v-if="renderLyricLines.length === 1" class="lyric-line"> &nbsp; </span>
</n-flex>
</div>
</n-config-provider>
@@ -80,6 +78,7 @@
<script setup lang="ts">
import { Position } from "@vueuse/core";
import { LyricConfig, LyricData, RenderLine } from "@/types/desktop-lyric";
import defaultDesktopLyricConfig from "@/assets/data/lyricConfig";
// 桌面歌词数据
const lyricData = reactive<LyricData>({
@@ -93,15 +92,7 @@ const lyricData = reactive<LyricData>({
// 桌面歌词配置
const lyricConfig = reactive<LyricConfig>({
isLock: false,
playedColor: "#fe7971",
unplayedColor: "#ccc",
shadowColor: "rgba(0, 0, 0, 0.5)",
fontFamily: "system-ui",
fontSize: 24,
isDoubleLine: true,
position: "both",
limitBounds: false,
...defaultDesktopLyricConfig,
});
// 桌面歌词元素
@@ -223,6 +214,68 @@ useDraggable(desktopLyricRef, {
},
});
// 监听窗口大小变化
const { height: winHeight } = useWindowSize();
/**
* 根据窗口高度计算字体大小
* 线性映射并取整,范围 20-96
*/
const computedFontSize = computed(() => {
const h = Number(winHeight?.value ?? 0);
const minH = 140;
const maxH = 360;
const minF = 20;
const maxF = 96;
if (!Number.isFinite(h) || h <= minH) return minF;
if (h >= maxH) return maxF;
const ratio = (h - minH) / (maxH - minH);
return Math.round(minF + ratio * (maxF - minF));
});
// 监听字体大小变化,同步更新窗口高度
watch(
computedFontSize,
(size) => {
if (!Number.isFinite(size)) return;
if (size === lyricConfig.fontSize) return;
const next = { fontSize: size };
window.electron.ipcRenderer.send("update-desktop-lyric-option", next, true);
},
{ immediate: true },
);
/**
* 根据字体大小计算窗口高度20-96 <-> 140-360
* @param size 字体大小
* @returns 窗口高度
*/
const fontSizeToHeight = (size: number) => {
const minH = 140;
const maxH = 360;
const minF = 20;
const maxF = 96;
const s = Math.min(Math.max(Math.round(size), minF), maxF);
const ratio = (s - minF) / (maxF - minF);
return Math.round(minH + ratio * (maxH - minH));
};
// 防抖推送窗口高度更新,避免频繁抖动
const pushWindowHeight = useDebounceFn((nextHeight: number) => {
if (!Number.isFinite(nextHeight)) return;
window.electron.ipcRenderer.send("update-window-height", nextHeight);
}, 100);
// 监听配置中的字体大小变化,同步更新窗口高度
watch(
() => lyricConfig.fontSize,
(size) => {
const height = fontSizeToHeight(size);
if (height) pushWindowHeight(height);
},
{ immediate: true },
);
// 发送至主进程
const sendToMain = (eventName: string, ...args: any[]) => {
window.electron.ipcRenderer.send(eventName, ...args);
@@ -253,6 +306,9 @@ onMounted(() => {
height: 100%;
}
.desktop-lyric {
display: flex;
flex-direction: column;
height: 100%;
color: #fff;
background-color: transparent;
padding: 12px;
@@ -306,10 +362,11 @@ onMounted(() => {
}
}
.lyric-container {
height: 100%;
padding: 0 8px;
.lyric-line {
// 单行
width: 100%;
line-height: normal;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@@ -336,7 +393,7 @@ onMounted(() => {
}
&:hover {
&:not(.locked) {
background-color: rgba(0, 0, 0, 0.3);
background-color: rgba(0, 0, 0, 0.6);
.header {
opacity: 1;
}
@@ -352,9 +409,9 @@ onMounted(() => {
}
</style>
<!-- <style>
<style>
body {
background-color: transparent !important;
/* background-image: url("https://picsum.photos/1920/1080"); */
}
</style> -->
</style>

View File

@@ -10,7 +10,7 @@
"electron/main/index.d.ts",
"electron/preload/index.d.ts",
"electron/preload/index.ts",
"dist/lastfm.ts"
"src/assets/data/*"
],
"compilerOptions": {
"composite": true,