parent
5846c05e08
commit
5c68eb8322
@ -0,0 +1,13 @@
|
|||||||
|
// 均衡器效果
|
||||||
|
|
||||||
|
import styles from './index.module.css';
|
||||||
|
|
||||||
|
export default function Equalizer({ active }: { active: boolean }) {
|
||||||
|
return (
|
||||||
|
<div className={`${styles.equalizer} ${!active && styles.paused}`}>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -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: #c43737ff;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,43 +0,0 @@
|
|||||||
/**
|
|
||||||
* 歌曲卡片
|
|
||||||
*/
|
|
||||||
'use client';
|
|
||||||
|
|
||||||
import { useShallow } from 'zustand/react/shallow';
|
|
||||||
|
|
||||||
import { SongCard } from '@/components';
|
|
||||||
import useAudioStore from '@/store/audio';
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
listId: string;
|
|
||||||
songList: SongInfo[];
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function JournalItem({ listId, songList, className }: Props) {
|
|
||||||
const { setPlayList, setAudioId, playListId } = useAudioStore(
|
|
||||||
useShallow((state) => ({
|
|
||||||
setAudioId: state.setAudioId,
|
|
||||||
setPlayList: state.setPlayList,
|
|
||||||
playListId: state.playListId,
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
|
|
||||||
const handlePlayList = (id: string) => {
|
|
||||||
// 正在播放其他歌单
|
|
||||||
if (playListId !== listId) {
|
|
||||||
setPlayList({ id: listId, list: songList });
|
|
||||||
}
|
|
||||||
|
|
||||||
// 正在播放当前歌单
|
|
||||||
setAudioId(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={`${className}`}>
|
|
||||||
{songList.map((song: SongInfo) => (
|
|
||||||
<SongCard key={song.id} {...song} onPlay={(audioId: string) => handlePlayList(audioId)} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* 歌曲卡片
|
||||||
|
*/
|
||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useShallow } from 'zustand/react/shallow';
|
||||||
|
|
||||||
|
import { SongCard } from '@/components';
|
||||||
|
import useAudioStore from '@/store/audio';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
listId: string;
|
||||||
|
songList: SongInfo[];
|
||||||
|
className?: string;
|
||||||
|
/** 收藏按钮的显示逻辑
|
||||||
|
* always: 总是显示
|
||||||
|
* playing: 播放时显示
|
||||||
|
*/
|
||||||
|
collectType?: 'always' | 'playing';
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function JournalItem({ songList, className, collectType = 'always' }: Props) {
|
||||||
|
const { playState, audioId, setPlayState, setAudioId, setPlayList } = useAudioStore(
|
||||||
|
useShallow((state) => ({
|
||||||
|
playState: state.playState,
|
||||||
|
audioId: state.audioId,
|
||||||
|
setPlayState: state.setPlayState,
|
||||||
|
setAudioId: state.setAudioId,
|
||||||
|
setPlayList: state.setPlayList,
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
const handlePlayList = (id: string) => {
|
||||||
|
if (!id) return;
|
||||||
|
if (id === audioId) {
|
||||||
|
setPlayState(!playState);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 设置播放列表、音频id
|
||||||
|
setPlayList(songList);
|
||||||
|
setAudioId(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`${className}`}>
|
||||||
|
{songList.map((item: SongInfo) => (
|
||||||
|
<SongCard
|
||||||
|
key={item.id}
|
||||||
|
{...item}
|
||||||
|
playState={playState}
|
||||||
|
showEq={item.id === audioId}
|
||||||
|
onPlay={(audioId: string) => handlePlayList(audioId)}
|
||||||
|
showCollect={collectType === 'always' || (collectType === 'playing' && item.id === audioId)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in new issue