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