import useLyric from '@/web/hooks/useLyric' import { player } from '@/web/store' import { motion, useMotionValue } from 'framer-motion' import { lyricParser } from '@/web/utils/lyric' import { useWindowSize } from 'react-use' import { useEffect, useLayoutEffect, useMemo, useState } from 'react' import { useSnapshot } from 'valtio' import cx from 'classnames' const Lyric = ({ className }: { className?: string }) => { // const ease = [0.5, 0.2, 0.2, 0.8] const playerSnapshot = useSnapshot(player) const track = useMemo(() => playerSnapshot.track, [playerSnapshot.track]) const { data: lyricRaw } = useLyric({ id: track?.id ?? 0 }) const lyric = useMemo(() => { return lyricRaw && lyricParser(lyricRaw) }, [lyricRaw]) const [progress, setProgress] = useState(0) useEffect(() => { const timer = setInterval(() => { setProgress(player.howler.seek() + 0.3) }, 300) return () => clearInterval(timer) }, []) const currentIndex = useMemo(() => { return (lyric?.lyric.findIndex(({ time }) => time > progress) ?? 1) - 1 }, [lyric?.lyric, progress]) const y = useMotionValue(1000) const { height: windowHight } = useWindowSize() useLayoutEffect(() => { const top = ( document.getElementById('lyrics')?.children?.[currentIndex] as any )?.offsetTop if (top) { y.set((windowHight / 9) * 4 - top) } }, [currentIndex, windowHight, y]) useEffect(() => { y.set(0) }, [track, y]) return (
{lyric?.lyric.map(({ content, time }, index) => { return ( currentIndex && index < currentIndex + 8 ? 0.2 : 0, transitionProperty: index > currentIndex - 2 && index < currentIndex + 8 ? 'transform, opacity' : 'none', transitionTimingFunction: index > currentIndex - 2 && index < currentIndex + 8 ? 'cubic-bezier(0.5, 0.2, 0.2, 0.8)' : 'none', transitionDelay: `${ index < currentIndex + 8 && index > currentIndex ? 0.04 * (index - currentIndex) : 0 }s`, }} > {content} ) })}
) } export default Lyric