feat: 优化逐字歌词效果,桌面歌词添加逐字歌词效果

This commit is contained in:
alger
2025-10-12 17:11:48 +08:00
parent 77f3069e67
commit a5d3ff359c
8 changed files with 351 additions and 82 deletions
@@ -49,27 +49,31 @@
@scroll="handleScroll"
>
<div class="lyrics-padding-top"></div>
<!-- 无时间戳歌词提示 -->
<div v-if="!supportAutoScroll" class="lyric-line no-scroll-tip">
<span>本歌词不支持自动滚动</span>
</div>
<div
v-for="(item, index) in lrcArray"
:key="index"
:id="`lyric-line-${index}`"
class="lyric-line"
:class="{ 'now-text': index === nowIndex, 'hover-text': item.text }"
@click="jumpToLyricTime(index)"
:class="{
'now-text': index === nowIndex,
'hover-text': item.text && item.startTime !== -1
}"
@click="item.startTime !== -1 ? jumpToLyricTime(index) : null"
>
<!-- 逐字歌词显示 -->
<div
v-if="item.hasWordByWord && item.words && item.words.length > 0"
class="word-by-word-lyric"
>
<span
v-for="(word, wordIndex) in item.words"
:key="wordIndex"
class="lyric-word"
:style="getWordStyle(index, wordIndex, word)"
<template v-for="(word, wordIndex) in item.words" :key="wordIndex">
<span class="lyric-word" :style="getWordStyle(index, wordIndex, word)">
{{ word.text }} </span
><span class="lyric-word" v-if="word.space">&nbsp;</span></template
>
{{ word.text }}
</span>
</div>
<!-- 普通歌词显示 -->
<span v-else :style="getLrcStyle(index)">{{ item.text }}</span>
@@ -247,27 +251,31 @@
@scroll="handleScroll"
>
<div class="lyrics-padding-top"></div>
<!-- 无时间戳歌词提示 -->
<div v-if="!supportAutoScroll" class="lyric-line no-scroll-tip">
<span>本歌词不支持自动滚动</span>
</div>
<div
v-for="(item, index) in lrcArray"
:key="index"
:id="`landscape-lyric-line-${index}`"
class="lyric-line"
:class="{ 'now-text': index === nowIndex, 'hover-text': item.text }"
@click="jumpToLyricTime(index)"
:class="{
'now-text': index === nowIndex,
'hover-text': item.text && item.startTime !== -1
}"
@click="item.startTime !== -1 ? jumpToLyricTime(index) : null"
>
<!-- 逐字歌词显示 -->
<div
v-if="item.hasWordByWord && item.words && item.words.length > 0"
class="word-by-word-lyric"
>
<span
v-for="(word, wordIndex) in item.words"
:key="wordIndex"
class="lyric-word"
:style="getWordStyle(index, wordIndex, word)"
<template v-for="(word, wordIndex) in item.words" :key="wordIndex">
<span class="lyric-word" :style="getWordStyle(index, wordIndex, word)">
{{ word.text }} </span
><span class="lyric-word" v-if="word.space">&nbsp;</span></template
>
{{ word.text }}
</span>
</div>
<!-- 普通歌词显示 -->
<span v-else :style="getLrcStyle(index)">{{ item.text }}</span>
@@ -458,6 +466,10 @@ const showFullLyricScreen = () => {
});
};
const supportAutoScroll = computed(() => {
return lrcArray.value.length > 0 && lrcArray.value[0].startTime !== -1;
});
// 关闭全屏歌词
const closeFullLyrics = () => {
showFullLyrics.value = false;
@@ -476,6 +488,11 @@ const scrollToCurrentLyric = (immediate = false, customScrollerRef?: HTMLElement
return;
}
if (!supportAutoScroll.value) {
console.log('歌词不支持自动滚动');
return;
}
// 如果用户正在手动滚动,不打断他们的操作
if (isTouchScrolling.value && !immediate) {
return;
@@ -1681,6 +1698,16 @@ const getWordStyle = (lineIndex: number, _wordIndex: number, word: any) => {
color: var(--text-color-primary);
opacity: 0.8;
&.no-scroll-tip {
@apply text-base opacity-60 cursor-default py-2;
color: var(--text-color-primary);
font-weight: normal;
span {
padding-right: 0;
}
}
span {
background-clip: text !important;
-webkit-background-clip: text !important;
@@ -1712,6 +1739,7 @@ const getWordStyle = (lineIndex: number, _wordIndex: number, word: any) => {
line-height: inherit;
cursor: inherit;
position: relative;
padding-right: 0 !important;
&:hover {
background-color: rgba(255, 255, 255, 0.1);