diff --git a/src/components/header/NavTools.tsx b/src/components/header/NavTools.tsx index e7a8cde..e566985 100644 --- a/src/components/header/NavTools.tsx +++ b/src/components/header/NavTools.tsx @@ -19,16 +19,51 @@ export function Social() { export function Sound() { const [active, setActive] = useState(arknightsConfig?.bgm?.autoplay ?? false) + const [volume, setVolume] = useState(active ? 1 : 0) const audioRef = useRef(null) + const [isFading, setIsFading] = useState(false); + const fadeIntervalRef = useRef(null); useEffect(() => { if (audioRef.current) { - if (active) audioRef.current.play().catch(e => console.error(e)); - else audioRef.current.pause() + const audio = audioRef.current; + + const handleFade = (targetVolume: number) => { + setIsFading(true); + if (fadeIntervalRef.current) clearInterval(fadeIntervalRef.current); + + fadeIntervalRef.current = setInterval(() => { + if ((targetVolume === 1 && audio.volume < 1) || (targetVolume === 0 && audio.volume > 0)) { + audio.volume = Math.max(0, Math.min(1, audio.volume + (targetVolume === 1 ? 0.25 : -0.25))); + setVolume(audio.volume); + } else { + if (fadeIntervalRef.current) clearInterval(fadeIntervalRef.current); + setIsFading(false); + if (targetVolume === 0) audio.pause(); + } + }, 100) as unknown as number; + }; + + if (active) { + audio.play().catch(e => console.error(e)); + handleFade(1); + } else { + handleFade(0); + } + } + + return () => { + if (fadeIntervalRef.current) clearInterval(fadeIntervalRef.current); + }; + }, [active]); + + const handleClick = () => { + if (!isFading) { + setActive(!active); } - }, [active]) + }; - return
setActive(!active)}> + return