From b01cc47566b00e8830adf7e1718d7948e34adb5b Mon Sep 17 00:00:00 2001 From: alikia2x Date: Wed, 5 Feb 2025 04:57:09 +0800 Subject: [PATCH] improve: performance by modifing template --- .../core/components/lyrics/lyricLine.svelte | 130 ++++++++---------- .../web/src/routes/play/[id]/+page.svelte | 2 +- 2 files changed, 59 insertions(+), 73 deletions(-) diff --git a/packages/core/components/lyrics/lyricLine.svelte b/packages/core/components/lyrics/lyricLine.svelte index 17e2d0c..dd9139f 100644 --- a/packages/core/components/lyrics/lyricLine.svelte +++ b/packages/core/components/lyrics/lyricLine.svelte @@ -41,17 +41,16 @@ let prevRealTime: number | undefined = undefined; let lastRealY: number | undefined = undefined; let lastRealTime: number | undefined = undefined; - const INTERVAL = 1; // 可调节的插值间隔(0-1) + const INTERPOLATED_RATE = 0; // 可调节的插值间隔(0-1) function updateY(timestamp: number) { if (stopped) return; - // 记录真实帧信息 const currentTime = new Date().getTime(); - const isRealFrame = INTERVAL === 0 || Math.random() < INTERVAL; + const isRealFrame = Math.random() > INTERPOLATED_RATE; if (isRealFrame) { - // 真实物理帧 + // 真实物理帧处理 if (lastUpdateY === undefined) { lastUpdateY = currentTime; } @@ -62,31 +61,35 @@ prevRealTime = lastRealTime; // 更新物理状态 - time = (currentTime - lastUpdateY) / 1000; - springY.update(time); + const deltaTime = (currentTime - lastUpdateY) / 1000; + springY.update(deltaTime); positionY = springY.getCurrentPosition(); // 记录当前真实帧数据 lastRealY = positionY; lastRealTime = currentTime; lastUpdateY = currentTime; - // 无论是否真实帧都继续请求动画帧(保持动画流畅) + + // 继续请求动画帧 if (!springY?.arrived() && !stopped && !we_are_scrolling) { requestAnimationFrame(updateY); } - } else if ( - prevRealY !== undefined && - prevRealTime !== undefined && - lastRealY !== undefined && - lastRealTime !== undefined - ) { - // 插值帧 - const timeSinceLastReal = currentTime - lastRealTime; - const deltaT = timeSinceLastReal / 1000; - const velocity = (lastRealY - prevRealY) / ((lastRealTime - prevRealTime) / 1000); + } else { + // 插值帧处理 + if (lastRealY !== undefined && lastRealTime !== undefined) { + const timeSinceLastReal = currentTime - lastRealTime; + const deltaT = timeSinceLastReal / 1000; - positionY = lastRealY + velocity * deltaT; - // 无论是否真实帧都继续请求动画帧(保持动画流畅) + // 计算速度(如果有前一次真实帧数据) + let velocity = 0; + if (prevRealY !== undefined && prevRealTime !== undefined && lastRealTime !== prevRealTime) { + velocity = (lastRealY - prevRealY) / ((lastRealTime - prevRealTime) / 1000); + } + + positionY = lastRealY + velocity * deltaT; + } + + // 无论是否成功插值都保持动画流畅 if (!stopped && !we_are_scrolling) { requestAnimationFrame(updateY); } @@ -206,50 +209,19 @@ export const getRef = () => ref; - // Calculate if the current character should be highlighted based on progress - const isCharacterHighlighted = (line: ScriptItem, word: LyricWord, charIndex: number, progress: number) => { - const charProgress = getCharacterProgress(word, charIndex); - return line.start <= progress && progress <= line.end && progress > charProgress; - }; - - // Get the progress timing for a specific character in a word - const getCharacterProgress = (word: LyricWord, charIndex: number) => { - const { startTime, endTime } = word; + let processedChars = line.words?.flatMap((word) => { + const { startTime, endTime, word: text } = word; const wordDuration = endTime - startTime; - return wordDuration * (charIndex / word.word.length) + startTime; - }; + return text.split('').map((chr, i) => { + const charProgress = startTime + wordDuration * (i / text.length); + const charDuration = wordDuration * ((i + 1) / text.length); + const transitionDur = charDuration < 0.6 ? null : charDuration / 1.6; + return { chr, charProgress, transitionDur }; + }); + }); - // Calculate the transition duration for a character - const getTransitionDuration = (word: LyricWord, charIndex: number) => { - const { startTime, endTime } = word; - const wordDuration = endTime - startTime; - const charDuration = wordDuration * ((charIndex + 1) / word.word.length); - - // If duration is less than 0.6s, we'll use CSS class with fixed duration - if (charDuration < 0.6) { - return null; - } - - // Otherwise, calculate custom duration - return charDuration / 1.6; - }; - - // Generate the CSS classes for a character - const getCharacterClasses = (line: ScriptItem, word: LyricWord, charIndex: number, progress: number) => { - const baseClasses = 'inline-block'; - const opacityClass = isCharacterHighlighted(line, word, charIndex, progress) - ? 'opacity-100 text-glow' - : 'opacity-35'; - - return `${baseClasses} ${opacityClass}`.trim(); - }; - - // Generate the style string for a character - const getCharacterStyle = (line: ScriptItem, word: LyricWord, charIndex: number, progress: number) => { - const duration = getTransitionDuration(word, charIndex); - const progressAtCurrentLine = progress <= line.end; - return duration && progressAtCurrentLine ? `transition-duration: ${duration}s;` : 'transition-duration: 200ms;'; - }; + // 新增:缓存当前行状态 + $: isActiveLine = line.start <= progress && progress <= line.end; @@ -282,17 +254,18 @@ {/if} {#if line.words !== undefined && line.words.length > 0} - {#each line.words as word} - {#if word.word} - {#each word.word.split('') as chr, i} - - {chr} - - {/each} - {/if} + {#each processedChars as char (char.charProgress)} + {@const isHighlighted = line.start <= progress && progress <= line.end && progress > char.charProgress} + {@const useCustomTransition = char.transitionDur !== null && isActiveLine} + + + {char.chr} + {/each} {:else} @@ -320,4 +293,17 @@ 0 15px 30px rgba(0, 0, 0, 0.11), 0 5px 15px rgba(0, 0, 0, 0.08); } + /* 预定义过渡类 */ + .char-transition { + transition-property: opacity; + transition-timing-function: ease-out; + } + + .fast-transition { + transition-duration: 200ms; + } + + .custom-transition { + transition-duration: var(--custom-duration); + } diff --git a/packages/web/src/routes/play/[id]/+page.svelte b/packages/web/src/routes/play/[id]/+page.svelte index 0db0d20..ea74432 100644 --- a/packages/web/src/routes/play/[id]/+page.svelte +++ b/packages/web/src/routes/play/[id]/+page.svelte @@ -209,7 +209,7 @@ if (audioPlayer === null) return; if ($userAdjustingProgress === false) currentProgress = audioPlayer.currentTime; progressBarRaw.set(audioPlayer.currentTime); - }, 20); + }, 70); } onMount(() => {