mirror of
https://github.com/jeffvli/feishin.git
synced 2026-07-12 13:39:58 +02:00
clean up animations
This commit is contained in:
@@ -22,7 +22,7 @@ const DEFAULT_ENDING_THRESHOLD = 0.5;
|
||||
const DEFAULT_LINE_LEAD_TIME_MS = 800;
|
||||
const RICHSYNC_TIMING_OFFSET_MS = 150;
|
||||
const SYNC_TIMING_OFFSET_MS = 115;
|
||||
const GLOW_DURATION_MULTIPLIER = 1.6;
|
||||
const HIGHLIGHT_DURATION_MULTIPLIER = 1.6;
|
||||
|
||||
export interface AnimEngineState {
|
||||
lastActiveElements: LineData[];
|
||||
@@ -58,6 +58,7 @@ export interface LineData {
|
||||
|
||||
export interface LyricsData {
|
||||
container: HTMLElement;
|
||||
lineIdPrefix: 'karaoke-line' | 'lyric';
|
||||
lines: LineData[];
|
||||
syncType: LyricsSyncType;
|
||||
}
|
||||
@@ -199,14 +200,14 @@ const completeSungVisualCleanup = (element: HTMLElement): void => {
|
||||
element.classList.remove(PAUSED_CLASS);
|
||||
};
|
||||
|
||||
const getRemainingGlowDurationSec = (
|
||||
const getRemainingHighlightDurationSec = (
|
||||
durationSec: number,
|
||||
startTimeSec: number,
|
||||
interpolatedTimeSec: number,
|
||||
): number => {
|
||||
const glowDurationSec = durationSec * GLOW_DURATION_MULTIPLIER;
|
||||
const highlightDurationSec = durationSec * HIGHLIGHT_DURATION_MULTIPLIER;
|
||||
const elapsedSec = Math.max(0, interpolatedTimeSec - startTimeSec);
|
||||
return Math.max(0, glowDurationSec - elapsedSec);
|
||||
return Math.max(0, highlightDurationSec - elapsedSec);
|
||||
};
|
||||
|
||||
const scheduleSungAnimationCleanup = (
|
||||
@@ -215,7 +216,7 @@ const scheduleSungAnimationCleanup = (
|
||||
startTimeSec: number,
|
||||
interpolatedTimeSec: number,
|
||||
): void => {
|
||||
const remainingSec = getRemainingGlowDurationSec(
|
||||
const remainingSec = getRemainingHighlightDurationSec(
|
||||
durationSec,
|
||||
startTimeSec,
|
||||
interpolatedTimeSec,
|
||||
@@ -373,6 +374,7 @@ export const buildLyricsDataFromDom = ({
|
||||
|
||||
return {
|
||||
container,
|
||||
lineIdPrefix,
|
||||
lines,
|
||||
syncType,
|
||||
};
|
||||
@@ -612,7 +614,8 @@ export const tickLyricsAnimation = (state: AnimEngineState, opts: TickOptions):
|
||||
const interpolatedTimeSec = playbackTimeSec + timingOffsetMs / 1000;
|
||||
const leadTimeSec = (opts.lineLeadTimeMs ?? DEFAULT_LINE_LEAD_TIME_MS) / 1000;
|
||||
|
||||
const { lines, syncType } = lyricsData;
|
||||
const { lineIdPrefix, lines, syncType } = lyricsData;
|
||||
const isLineSyncMode = lineIdPrefix === 'lyric';
|
||||
if (syncType === 'none') {
|
||||
return -1;
|
||||
}
|
||||
@@ -638,12 +641,16 @@ export const tickLyricsAnimation = (state: AnimEngineState, opts: TickOptions):
|
||||
const time = lineData.time;
|
||||
const nextTime =
|
||||
index + 1 < lines.length ? lines[index + 1].time : Number.POSITIVE_INFINITY;
|
||||
const isInLineWindow =
|
||||
playbackTimeSec < nextTime || playbackTimeSec < time + lineData.duration;
|
||||
|
||||
const isUpcoming =
|
||||
playbackTimeSec >= time - leadTimeSec &&
|
||||
(playbackTimeSec < nextTime || playbackTimeSec < time + lineData.duration);
|
||||
const isScrollCandidate = playbackTimeSec >= time - leadTimeSec && isInLineWindow;
|
||||
|
||||
if (isUpcoming) {
|
||||
const isVisuallyActive = isLineSyncMode
|
||||
? playbackTimeSec >= time && isInLineWindow
|
||||
: isScrollCandidate;
|
||||
|
||||
if (isScrollCandidate) {
|
||||
activeElems.push(lineData);
|
||||
state.selectedElementIndex = index;
|
||||
activeLineIndex = index;
|
||||
@@ -651,19 +658,37 @@ export const tickLyricsAnimation = (state: AnimEngineState, opts: TickOptions):
|
||||
if (isPlaying && !lineData.isScrolled) {
|
||||
newLyricSelected = true;
|
||||
state.scroll.pendingScroll = true;
|
||||
lineData.element.classList.add(LINE_ACTIVE_CLASS);
|
||||
lineData.isScrolled = true;
|
||||
onLineActive?.(index);
|
||||
|
||||
if (!isLineSyncMode) {
|
||||
lineData.element.classList.add(LINE_ACTIVE_CLASS);
|
||||
}
|
||||
}
|
||||
} else if (lineData.isScrolled) {
|
||||
lineData.element.classList.remove(LINE_ACTIVE_CLASS);
|
||||
lineData.isScrolled = false;
|
||||
|
||||
if (!isLineSyncMode) {
|
||||
lineData.element.classList.remove(LINE_ACTIVE_CLASS);
|
||||
}
|
||||
}
|
||||
|
||||
if (isLineSyncMode) {
|
||||
if (isVisuallyActive) {
|
||||
lineData.element.classList.add(LINE_ACTIVE_CLASS);
|
||||
} else {
|
||||
lineData.element.classList.remove(LINE_ACTIVE_CLASS);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isPlaying) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isLineSyncMode && !lineData.hasWordCues) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const setUpEarly = 2;
|
||||
const effectiveEnd = Math.max(nextTime, time + lineData.duration + 0.05);
|
||||
const isLineInRange =
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
tickLyricsAnimation,
|
||||
} from '/@/renderer/features/lyrics/hooks/lyrics-animation-engine';
|
||||
import { SynchronizedLyrics } from '/@/shared/types/domain-types';
|
||||
import '/@/renderer/features/lyrics/styles/karaoke-animation.css';
|
||||
|
||||
export interface UseLyricsAnimationEngineOptions {
|
||||
animStateRef?: React.MutableRefObject<AnimEngineState>;
|
||||
|
||||
@@ -127,9 +127,6 @@ export const useSynchronizedLyricsBase = (settingsKey = 'default', offsetMs?: nu
|
||||
const resumeAutoscroll = useCallback(() => {
|
||||
userScrollingRef.current = false;
|
||||
resumeLyricsAutoscroll(scrollAnimStateRef.current);
|
||||
|
||||
const doc = document.getElementById(LYRICS_SCROLL_CONTAINER_ID) as HTMLElement;
|
||||
doc?.classList.remove('lyrics-user-scrolling');
|
||||
}, []);
|
||||
|
||||
const containerStyle = useMemo(
|
||||
@@ -198,7 +195,6 @@ export const useSynchronizedLyricsBase = (settingsKey = 'default', offsetMs?: nu
|
||||
|
||||
userScrollingRef.current = true;
|
||||
handleLyricsUserScroll(scrollAnimStateRef.current);
|
||||
container.classList.add('lyrics-user-scrolling');
|
||||
|
||||
if (scrollTimeoutRef.current) {
|
||||
clearTimeout(scrollTimeoutRef.current);
|
||||
@@ -206,7 +202,6 @@ export const useSynchronizedLyricsBase = (settingsKey = 'default', offsetMs?: nu
|
||||
|
||||
scrollTimeoutRef.current = setTimeout(() => {
|
||||
userScrollingRef.current = false;
|
||||
container.classList.remove('lyrics-user-scrolling');
|
||||
}, 3000);
|
||||
};
|
||||
|
||||
|
||||
@@ -99,29 +99,18 @@ const renderWordSpans = (
|
||||
...(durationMs > LONG_WORD_THRESHOLD_MS ? { 'data-long-word': true as const } : {}),
|
||||
};
|
||||
|
||||
if (hasFurigana) {
|
||||
return (
|
||||
<span key={wordKey} {...wordProps}>
|
||||
<span
|
||||
className="karaoke-word-text"
|
||||
dangerouslySetInnerHTML={{ __html: sanitizedHtml }}
|
||||
/>
|
||||
<span
|
||||
aria-hidden
|
||||
className="karaoke-word-highlight"
|
||||
dangerouslySetInnerHTML={{ __html: sanitizedHtml }}
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
key={wordKey}
|
||||
{...wordProps}
|
||||
dangerouslySetInnerHTML={{ __html: sanitizedHtml }}
|
||||
data-content={word.text}
|
||||
/>
|
||||
<span key={wordKey} {...wordProps}>
|
||||
<span
|
||||
className="karaoke-word-text"
|
||||
dangerouslySetInnerHTML={{ __html: sanitizedHtml }}
|
||||
/>
|
||||
<span
|
||||
aria-hidden
|
||||
className="karaoke-word-highlight"
|
||||
dangerouslySetInnerHTML={{ __html: sanitizedHtml }}
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -11,45 +11,39 @@
|
||||
initial-value: 0;
|
||||
}
|
||||
|
||||
/* Container-level line context blur/fade (karaoke + line sync) */
|
||||
.synchronized-karaoke-lyrics:has(.lyrics-line-active):not(.lyrics-user-scrolling)
|
||||
> :is(.karaoke-line, .lyric-line):not(
|
||||
/* Container-level line context blur/fade (karaoke sync only) */
|
||||
.synchronized-karaoke-lyrics:has(.lyrics-line-active)
|
||||
:is(.karaoke-line, .lyric-line):not(
|
||||
.lyrics-line-active,
|
||||
.lyrics-line-active ~ :is(.karaoke-line, .lyric-line)
|
||||
),
|
||||
.synchronized-lyrics:has(.lyrics-line-active):not(.lyrics-user-scrolling)
|
||||
> .lyric-line:not(.lyrics-line-active, .lyrics-line-active ~ .lyric-line) {
|
||||
opacity: 0.33;
|
||||
) {
|
||||
opacity: var(--lyric-opacity, 0.3);
|
||||
filter: blur(2.5px);
|
||||
}
|
||||
|
||||
.synchronized-karaoke-lyrics > :is(.karaoke-line, .lyric-line).lyrics-line-active,
|
||||
.synchronized-lyrics > .lyric-line.lyrics-line-active {
|
||||
.synchronized-karaoke-lyrics :is(.karaoke-line, .lyric-line).lyrics-line-active {
|
||||
opacity: 1 !important;
|
||||
filter: blur(0);
|
||||
}
|
||||
|
||||
.synchronized-karaoke-lyrics:has(.lyrics-line-active)
|
||||
> :is(.karaoke-line, .lyric-line).lyrics-line-active
|
||||
~ :is(.karaoke-line, .lyric-line),
|
||||
.synchronized-lyrics:has(.lyrics-line-active) > .lyric-line.lyrics-line-active ~ .lyric-line {
|
||||
opacity: 0.66;
|
||||
:is(.karaoke-line, .lyric-line).lyrics-line-active
|
||||
~ :is(.karaoke-line, .lyric-line) {
|
||||
opacity: var(--lyric-opacity, 0.3);
|
||||
filter: blur(0);
|
||||
}
|
||||
|
||||
.synchronized-karaoke-lyrics > :is(.karaoke-line, .lyric-line).lyrics-line-animating,
|
||||
.synchronized-lyrics > .lyric-line.lyrics-line-animating {
|
||||
.synchronized-karaoke-lyrics :is(.karaoke-line, .lyric-line).lyrics-line-animating {
|
||||
opacity: 1 !important;
|
||||
filter: blur(0) !important;
|
||||
}
|
||||
|
||||
.synchronized-karaoke-lyrics > :is(.karaoke-line, .lyric-line):hover,
|
||||
.synchronized-lyrics > .lyric-line:hover {
|
||||
.synchronized-karaoke-lyrics :is(.karaoke-line, .lyric-line):hover {
|
||||
opacity: 1 !important;
|
||||
filter: blur(0) !important;
|
||||
}
|
||||
|
||||
/* Word highlight via ::after pseudo-element gradient swipe */
|
||||
/* Word highlight via stacked text twin + gradient swipe */
|
||||
.karaoke-word {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
@@ -57,129 +51,21 @@
|
||||
color: rgb(from var(--theme-colors-foreground) r g b / var(--lyric-opacity, 0.3));
|
||||
overflow-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.karaoke-word:has(.karaoke-word-highlight) {
|
||||
display: inline-grid;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
.karaoke-word.sung {
|
||||
color: var(--theme-colors-foreground);
|
||||
}
|
||||
|
||||
.karaoke-line.lyrics-line-pre-animating,
|
||||
.karaoke-line.lyrics-line-pre-animating .karaoke-word {
|
||||
.karaoke-line.lyrics-line-pre-animating {
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.karaoke-word.lyrics-word-animating {
|
||||
animation: karaoke-wobble var(--karaoke-wobble-duration, 1s) forwards ease;
|
||||
animation-delay: var(--karaoke-anim-delay, 0s);
|
||||
animation-play-state: running;
|
||||
}
|
||||
|
||||
.karaoke-word.karaoke-furigana-word.lyrics-word-animating {
|
||||
transform: none;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
.karaoke-word.lyrics-word-animating.lyrics-word-paused {
|
||||
animation-play-state: paused;
|
||||
}
|
||||
|
||||
.karaoke-word::after {
|
||||
position: absolute;
|
||||
top: -2rem;
|
||||
left: -2rem;
|
||||
box-sizing: content-box;
|
||||
width: 100%;
|
||||
padding: 2rem;
|
||||
color: transparent;
|
||||
white-space: pre-wrap;
|
||||
pointer-events: none;
|
||||
content: attr(data-content);
|
||||
background-image: linear-gradient(
|
||||
90deg,
|
||||
var(--theme-colors-foreground)
|
||||
calc(
|
||||
100% * var(--lyric-transition-amount-start) - 4rem *
|
||||
var(--lyric-transition-amount-start) + 2rem
|
||||
),
|
||||
#0000
|
||||
calc(
|
||||
100% * var(--lyric-transition-amount-end) - 4rem *
|
||||
var(--lyric-transition-amount-end) + 2rem + 1px
|
||||
)
|
||||
);
|
||||
background-clip: text;
|
||||
opacity: 0;
|
||||
transition:
|
||||
--lyric-transition-amount-start 1s linear 1000s,
|
||||
--lyric-transition-amount-end 1s linear 1000s,
|
||||
opacity 0.5s ease;
|
||||
|
||||
--lyric-transition-amount-start: -0.2;
|
||||
--lyric-transition-amount-end: -0.1;
|
||||
--karaoke-glow-color: color(display-p3 1 1 1 / 0.01%);
|
||||
}
|
||||
|
||||
.karaoke-word[data-long-word]::after {
|
||||
--karaoke-glow-color: color(display-p3 1 1 1 / 100%);
|
||||
}
|
||||
|
||||
.karaoke-word.lyrics-word-pre-animating:not(.lyrics-word-animating)::after {
|
||||
opacity: 0;
|
||||
transition: none;
|
||||
|
||||
--lyric-transition-amount-start: -0.2;
|
||||
--lyric-transition-amount-end: -0.1;
|
||||
}
|
||||
|
||||
.karaoke-word.lyrics-word-pre-animating:not(.lyrics-word-animating, .karaoke-zero-dur)::after {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.karaoke-word.lyrics-word-animating::after {
|
||||
opacity: 1;
|
||||
transition-delay:
|
||||
var(--karaoke-swipe-delay, 0s), var(--karaoke-swipe-delay, 0s),
|
||||
var(--karaoke-anim-delay, 0s);
|
||||
transition-timing-function: linear, linear, ease;
|
||||
transition-duration:
|
||||
calc(var(--karaoke-duration, 1ms) * 1.6), calc(var(--karaoke-duration, 1ms) * 1.6),
|
||||
var(--karaoke-highlight-fade-in-duration, 0.33s);
|
||||
transition-property: --lyric-transition-amount-start, --lyric-transition-amount-end, opacity;
|
||||
animation: karaoke-glow calc(var(--karaoke-duration, 1ms) * 1.6) forwards ease-out;
|
||||
animation-delay: var(--karaoke-anim-delay, 0s);
|
||||
animation-play-state: running;
|
||||
will-change: --lyric-transition-amount-start, --lyric-transition-amount-end, opacity;
|
||||
|
||||
--lyric-transition-amount-start: 1.4;
|
||||
--lyric-transition-amount-end: 1.5;
|
||||
}
|
||||
|
||||
.karaoke-word.lyrics-word-animating.lyrics-word-paused::after {
|
||||
opacity: 0.5;
|
||||
transition-duration: 100000000s, 100000000s, 100000000s;
|
||||
animation-play-state: paused;
|
||||
|
||||
--lyric-transition-amount-start: 10;
|
||||
--lyric-transition-amount-end: 10;
|
||||
}
|
||||
|
||||
.karaoke-word.karaoke-rtl::after {
|
||||
background-image: linear-gradient(
|
||||
270deg,
|
||||
var(--theme-colors-foreground)
|
||||
calc(
|
||||
100% * var(--lyric-transition-amount-start) - 4rem *
|
||||
var(--lyric-transition-amount-start) + 2rem
|
||||
),
|
||||
#0000
|
||||
calc(
|
||||
100% * var(--lyric-transition-amount-end) - 4rem *
|
||||
var(--lyric-transition-amount-end) + 2rem + 1px
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
.karaoke-word.karaoke-bg-vocal {
|
||||
font-size: 0.675em;
|
||||
font-weight: 400;
|
||||
@@ -190,62 +76,12 @@
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.karaoke-word.karaoke-romaji-word::after {
|
||||
top: -1.25em;
|
||||
left: -1.25em;
|
||||
padding: 1.25em;
|
||||
background-image: linear-gradient(
|
||||
90deg,
|
||||
var(--theme-colors-foreground)
|
||||
calc(
|
||||
100% * var(--lyric-transition-amount-start) - 2.5em *
|
||||
var(--lyric-transition-amount-start) + 1.25em
|
||||
),
|
||||
#0000
|
||||
calc(
|
||||
100% * var(--lyric-transition-amount-end) - 2.5em *
|
||||
var(--lyric-transition-amount-end) + 1.25em + 1px
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
.karaoke-word.karaoke-romaji-word.karaoke-rtl::after {
|
||||
background-image: linear-gradient(
|
||||
270deg,
|
||||
var(--theme-colors-foreground)
|
||||
calc(
|
||||
100% * var(--lyric-transition-amount-start) - 2.5em *
|
||||
var(--lyric-transition-amount-start) + 1.25em
|
||||
),
|
||||
#0000
|
||||
calc(
|
||||
100% * var(--lyric-transition-amount-end) - 2.5em *
|
||||
var(--lyric-transition-amount-end) + 1.25em + 1px
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/* Furigana words use an HTML highlight twin instead of ::after */
|
||||
.karaoke-word:has(.karaoke-word-highlight) {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.karaoke-word:has(.karaoke-word-highlight)::after {
|
||||
display: none;
|
||||
content: none;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.karaoke-word-text {
|
||||
display: inline;
|
||||
.karaoke-word-text,
|
||||
.karaoke-word-highlight {
|
||||
grid-area: 1 / 1;
|
||||
}
|
||||
|
||||
.karaoke-word-highlight {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
color: transparent;
|
||||
overflow-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
@@ -264,11 +100,6 @@
|
||||
|
||||
--lyric-transition-amount-start: -0.2;
|
||||
--lyric-transition-amount-end: -0.1;
|
||||
--karaoke-glow-color: color(display-p3 1 1 1 / 0.01%);
|
||||
}
|
||||
|
||||
.karaoke-word[data-long-word] .karaoke-word-highlight {
|
||||
--karaoke-glow-color: color(display-p3 1 1 1 / 100%);
|
||||
}
|
||||
|
||||
.karaoke-word.lyrics-word-pre-animating:not(.lyrics-word-animating) .karaoke-word-highlight {
|
||||
@@ -294,9 +125,6 @@
|
||||
calc(var(--karaoke-duration, 1ms) * 1.6), calc(var(--karaoke-duration, 1ms) * 1.6),
|
||||
var(--karaoke-highlight-fade-in-duration, 0.33s);
|
||||
transition-property: --lyric-transition-amount-start, --lyric-transition-amount-end, opacity;
|
||||
animation: karaoke-glow calc(var(--karaoke-duration, 1ms) * 1.6) forwards ease-out;
|
||||
animation-delay: var(--karaoke-anim-delay, 0s);
|
||||
animation-play-state: running;
|
||||
will-change: --lyric-transition-amount-start, --lyric-transition-amount-end, opacity;
|
||||
|
||||
--lyric-transition-amount-start: 1.4;
|
||||
@@ -306,7 +134,6 @@
|
||||
.karaoke-word.lyrics-word-animating.lyrics-word-paused .karaoke-word-highlight {
|
||||
opacity: 0.5;
|
||||
transition-duration: 100000000s, 100000000s, 100000000s;
|
||||
animation-play-state: paused;
|
||||
|
||||
--lyric-transition-amount-start: 10;
|
||||
--lyric-transition-amount-end: 10;
|
||||
@@ -338,23 +165,3 @@
|
||||
.karaoke-word ruby rp {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@keyframes karaoke-wobble {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(-0.0375em);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes karaoke-glow {
|
||||
0% {
|
||||
filter: drop-shadow(0 0 0.8rem var(--karaoke-glow-color));
|
||||
}
|
||||
|
||||
100% {
|
||||
filter: drop-shadow(0 0 0 var(--karaoke-glow-color));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/* Container-level line context blur/fade (line-sync only) */
|
||||
.synchronized-lyrics .lyric-line {
|
||||
transition:
|
||||
filter 0.2s ease,
|
||||
opacity 0.2s ease,
|
||||
transform 0.2s ease;
|
||||
}
|
||||
|
||||
.synchronized-lyrics:has(.lyrics-line-active)
|
||||
.lyric-line:not(.lyrics-line-active, .lyrics-line-active ~ .lyric-line) {
|
||||
opacity: var(--lyric-opacity, 0.3);
|
||||
filter: blur(2.5px);
|
||||
}
|
||||
|
||||
.synchronized-lyrics .lyric-line.lyrics-line-active {
|
||||
opacity: 1 !important;
|
||||
filter: blur(0);
|
||||
}
|
||||
|
||||
.synchronized-lyrics:has(.lyrics-line-active) .lyric-line.lyrics-line-active ~ .lyric-line {
|
||||
opacity: var(--lyric-opacity, 0.3);
|
||||
filter: blur(0);
|
||||
}
|
||||
|
||||
.synchronized-lyrics .lyric-line.lyrics-line-animating {
|
||||
opacity: 1 !important;
|
||||
filter: blur(0) !important;
|
||||
}
|
||||
|
||||
.synchronized-lyrics .lyric-line:hover {
|
||||
opacity: 1 !important;
|
||||
filter: blur(0) !important;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
|
||||
import styles from './synchronized-karaoke-lyrics.module.css';
|
||||
|
||||
import '/@/renderer/features/lyrics/styles/karaoke-animation.css';
|
||||
import {
|
||||
findOverlayLineByTime,
|
||||
getLyricLineStartMs,
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
|
||||
import styles from './synchronized-lyrics.module.css';
|
||||
|
||||
import '/@/renderer/features/lyrics/styles/synchronized-lyrics-animation.css';
|
||||
import {
|
||||
findOverlayLineByTime,
|
||||
getLyricLineStartMs,
|
||||
|
||||
Reference in New Issue
Block a user