improve: lyric effect

This commit is contained in:
alikia2x (寒寒) 2024-10-25 00:49:00 +08:00
parent 3ee8361669
commit 57fd2f626b
Signed by: alikia2x
GPG Key ID: 56209E0CCD8420C6
2 changed files with 28 additions and 13 deletions

View File

@ -5,7 +5,7 @@
import type { Spring } from '$lib/graphics/spring/spring'; import type { Spring } from '$lib/graphics/spring/spring';
const viewportWidth = document.documentElement.clientWidth; const viewportWidth = document.documentElement.clientWidth;
const scaleCurrentLine = viewportWidth > 640 ? 1.02 : 1.045 ; const scaleCurrentLine = viewportWidth > 640 ? 1.02 : 1.045;
export let line: ScriptItem; export let line: ScriptItem;
export let index: number; export let index: number;
@ -112,8 +112,8 @@
lastPosY = pos.y; lastPosY = pos.y;
positionX = pos.x; positionX = pos.x;
positionY = pos.y; positionY = pos.y;
springX = createSpring(pos.x, pos.x, 0.126, 0.8); springX = createSpring(pos.x, pos.x, 0.1, 0.67);
springY = createSpring(pos.y, pos.y, 0.126, 0.8); springY = createSpring(pos.y, pos.y, 0.1, 0.67);
}; };
export const stop = () => { export const stop = () => {
@ -127,30 +127,35 @@
<!-- svelte-ignore a11y-no-static-element-interactions --> <!-- svelte-ignore a11y-no-static-element-interactions -->
<div <div
style="transform: translate3d({positionX}px, {positionY}px, 0); scale: {scale}; style="transform: translate3d({positionX}px, {positionY}px, 0); scale: {scale};
transition-property: scale, opacity; transition-duration: 0.5s; transition-timing-function: ease-in-out; opacity: {opacity}; transition-property: scale, opacity, text-shadow; transition-duration: 0.5s; transition-timing-function: ease-in-out; opacity: {opacity};
transform-origin: center left;" transform-origin: center left;"
class="absolute z-50 w-full pr-12 lg:pr-16 cursor-default py-5" class="absolute z-50 w-full pr-12 lg:pr-16 cursor-default py-5"
bind:this={ref} bind:this={ref}
on:touchstart={() => { on:touchstart={() => {
clickMask.style.backgroundColor = "rgba(255,255,255,.3)"; clickMask.style.backgroundColor = 'rgba(255,255,255,.3)';
}} }}
on:touchend={() => { on:touchend={() => {
clickMask.style.backgroundColor = "transparent"; clickMask.style.backgroundColor = 'transparent';
}} }}
on:click={() => { on:click={() => {
lyricClick(index); lyricClick(index);
}} }}
> >
<span class="absolute w-[calc(100%-2.5rem)] lg:w-[calc(100%-2.75rem)] h-full <span
-translate-x-2 lg:-translate-x-5 -translate-y-5 rounded-lg duration-300 lg:hover:bg-[rgba(255,255,255,.15)]" bind:this={clickMask}> class="absolute w-[calc(100%-2.5rem)] lg:w-[calc(100%-3rem)] h-full
-translate-x-2 lg:-translate-x-5 -translate-y-5 rounded-lg duration-300 lg:hover:bg-[rgba(255,255,255,.15)]"
bind:this={clickMask}
>
</span> </span>
{#if debugMode} {#if debugMode}
<span class="text-lg absolute -translate-y-7"> <span class="text-lg absolute -translate-y-7">
{index}: duration: {(line.end - line.start).toFixed(3)}, {line.start.toFixed(3)}~{line.end.toFixed(3)} {index}: duration: {(line.end - line.start).toFixed(3)}, {line.start.toFixed(3)}~{line.end.toFixed(3)}
</span> </span>
{/if} {/if}
<span class={`text-white text-[2rem] leading-9 lg:text-5xl lg:leading-[4rem] font-semibold text-shadow-lg mr-4`}> <span
class={`text-white text-[2rem] leading-9 lg:text-5xl lg:leading-[4rem] font-semibold text-shadow-lg mr-4
${isCurrentLyric ? 'text-glow' : ''}`}
>
{line.text} {line.text}
</span> </span>
{#if line.translation} {#if line.translation}
@ -160,3 +165,13 @@
</span> </span>
{/if} {/if}
</div> </div>
<style>
.text-glow {
text-shadow:
0 0 3px #ffffff2c,
0 0 6px #ffffff2c,
0 15px 30px rgba(0, 0, 0, 0.11),
0 5px 15px rgba(0, 0, 0, 0.08);
}
</style>

View File

@ -8,7 +8,7 @@
// constants // constants
const viewportHeight = document.documentElement.clientHeight; const viewportHeight = document.documentElement.clientHeight;
const viewportWidth = document.documentElement.clientWidth; const viewportWidth = document.documentElement.clientWidth;
const marginY = viewportWidth > 640 ? 36 : 0 ; const marginY = viewportWidth > 640 ? 12 : 0 ;
const blurRatio = viewportWidth > 640 ? 1 : 1.4; const blurRatio = viewportWidth > 640 ? 1 : 1.4;
const currentLyrictTop = viewportWidth > 640 ? viewportHeight * 0.12 : viewportHeight * 0.05; const currentLyrictTop = viewportWidth > 640 ? viewportHeight * 0.12 : viewportHeight * 0.05;
const deceleration = 0.95; // Velocity decay factor for inertia const deceleration = 0.95; // Velocity decay factor for inertia
@ -57,7 +57,7 @@
} }
function initLyricTopList() { function initLyricTopList() {
let cumulativeHeight = 0; let cumulativeHeight = currentLyrictTop;
for (let i = 0; i < lyricLines.length; i++) { for (let i = 0; i < lyricLines.length; i++) {
const c = lyricComponents[i]; const c = lyricComponents[i];
lyricElements.push(c.getRef()); lyricElements.push(c.getRef());
@ -80,7 +80,7 @@
if (i <= currentLyricIndex) { if (i <= currentLyricIndex) {
delay = 0; delay = 0;
} else { } else {
delay = 0.013 + Math.min(Math.min(currentLyricDuration, 0.1), 0.075 * (i - currentLyricIndex)); delay = Math.min(Math.min(currentLyricDuration, 0.6), 0.064 * (i - currentLyricIndex));
} }
const offset = Math.abs(i - currentLyricIndex); const offset = Math.abs(i - currentLyricIndex);
let blurRadius = Math.min(offset * blurRatio, 16); let blurRadius = Math.min(offset * blurRatio, 16);