parent
6ce2f585d3
commit
59b56124eb
After Width: | Height: | Size: 3.9 KiB |
@ -0,0 +1,36 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import Image from 'next/image';
|
||||
|
||||
import { useJournalAudioContext } from '@/context/JournalAudioContext';
|
||||
|
||||
export default function JournalAudioCtrlBtn() {
|
||||
const { audioPlayer, songList, curSong, setCurSong, playing, setPlaying } = useJournalAudioContext();
|
||||
|
||||
const handleClick = () => {
|
||||
if (curSong === undefined) {
|
||||
setCurSong?.(songList?.[0]);
|
||||
}
|
||||
setPlaying?.(!playing);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (curSong?.src && audioPlayer?.audio) {
|
||||
playing ? audioPlayer?.audio?.play() : audioPlayer?.audio?.pause();
|
||||
}
|
||||
}, [curSong?.src, playing, audioPlayer?.audio]);
|
||||
|
||||
return (
|
||||
<Image
|
||||
className="w-[60px] h-[60px] absolute top-[-30px] right-[16px]"
|
||||
width={60}
|
||||
height={60}
|
||||
unoptimized
|
||||
src={`/img/${playing ? 'icon_pause.png' : 'icon_play.png'}`}
|
||||
alt="play_pause"
|
||||
onClick={handleClick}
|
||||
/>
|
||||
);
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
.equalizer {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 6px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.equalizer span {
|
||||
width: 2px;
|
||||
border-radius: 4px;
|
||||
background: #b44343ff;
|
||||
animation: up-and-down 2s linear infinite;
|
||||
}
|
||||
|
||||
.equalizer span:nth-child(1) {
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
.equalizer span:nth-child(2) {
|
||||
}
|
||||
|
||||
.equalizer span:nth-child(3) {
|
||||
animation-delay: 0.7s;
|
||||
}
|
||||
|
||||
.equalizer.paused span {
|
||||
animation-play-state: paused;
|
||||
}
|
||||
|
||||
@keyframes up-and-down {
|
||||
0%,
|
||||
100% {
|
||||
clip-path: inset(27% 0 0 0);
|
||||
}
|
||||
|
||||
10% {
|
||||
clip-path: inset(17% 0 0 0);
|
||||
}
|
||||
|
||||
20% {
|
||||
clip-path: inset(55% 0 0 0);
|
||||
}
|
||||
|
||||
30% {
|
||||
clip-path: inset(30% 0 0 0);
|
||||
}
|
||||
|
||||
40% {
|
||||
clip-path: inset(13% 0 0 0);
|
||||
}
|
||||
|
||||
50% {
|
||||
clip-path: inset(38% 0 0 0);
|
||||
}
|
||||
|
||||
60% {
|
||||
clip-path: inset(80% 0 0 0);
|
||||
}
|
||||
|
||||
70% {
|
||||
clip-path: inset(21% 0 0 0);
|
||||
}
|
||||
|
||||
80% {
|
||||
clip-path: inset(0% 0 0 0);
|
||||
}
|
||||
|
||||
90% {
|
||||
clip-path: inset(36% 0 0 0);
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useRef } from 'react';
|
||||
|
||||
import AudioPlayer from '@/components/AudioPlayer';
|
||||
import type { IAudioPlayerRef } from '@/components/AudioPlayer';
|
||||
import JournalAudioCtrlBtn from '@/components/JournalAudioCtrlBtn';
|
||||
import SongItem from '@/components/SongItem';
|
||||
|
||||
import { JournalAudioContext } from '@/context/JournalAudioContext';
|
||||
|
||||
export default function SongList({ list }: { list: ISong[] }) {
|
||||
const audioPlayerRef = useRef<IAudioPlayerRef>(null);
|
||||
const [curSong, setCurSong] = useState<ISong | undefined>();
|
||||
const [playing, setPlaying] = useState(false);
|
||||
|
||||
const providerVal = {
|
||||
audioPlayer: audioPlayerRef?.current,
|
||||
songList: list,
|
||||
curSong,
|
||||
setCurSong,
|
||||
playing,
|
||||
setPlaying,
|
||||
};
|
||||
|
||||
return (
|
||||
<JournalAudioContext.Provider value={providerVal}>
|
||||
<JournalAudioCtrlBtn />
|
||||
|
||||
<h5 className="mb-[12px] text-[#000000f2] text-[15px] h-[18px]">共{list?.length || 0}首</h5>
|
||||
{list?.map((song: ISong) => <SongItem key={song.id} data={song} />)}
|
||||
|
||||
<div className="hidden">
|
||||
<AudioPlayer ref={audioPlayerRef} autoPlay={false} src={curSong?.src} />
|
||||
</div>
|
||||
</JournalAudioContext.Provider>
|
||||
);
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
import { createContext, useContext } from 'react';
|
||||
|
||||
import type { IAudioPlayerRef } from '@/components/AudioPlayer';
|
||||
|
||||
interface IJournalAudioContext {
|
||||
audioPlayer: IAudioPlayerRef | null;
|
||||
songList?: ISong[];
|
||||
curSong?: ISong;
|
||||
setCurSong?: any;
|
||||
playing?: boolean;
|
||||
setPlaying?: any;
|
||||
}
|
||||
|
||||
const JournalAudioContext = createContext<IJournalAudioContext>({
|
||||
audioPlayer: null,
|
||||
});
|
||||
JournalAudioContext.displayName = 'JournalAudioContext';
|
||||
|
||||
export const useJournalAudioContext = () => useContext(JournalAudioContext);
|
||||
|
||||
export { JournalAudioContext };
|
Loading…
Reference in new issue