diff --git a/public/img/audio-player/CD.png b/public/img/audio-player/CD.png
new file mode 100644
index 0000000..ae790dd
Binary files /dev/null and b/public/img/audio-player/CD.png differ
diff --git a/src/components/AudioPlayer/Player.tsx b/src/components/AudioPlayer/Player.tsx
index f17a820..87237e4 100644
--- a/src/components/AudioPlayer/Player.tsx
+++ b/src/components/AudioPlayer/Player.tsx
@@ -11,15 +11,23 @@ import PlayerControl from './PlayerControl';
import useAudioStore from '@/store/audio';
-export default function AudioPlayer({ className }: { className?: string }) {
- const { audioId, order, playQueue, switchSongByDiff, setOrder } = useAudioStore(
+export default function AudioPlayer({
+ className,
+ onSwitchShowCard,
+}: {
+ className?: string;
+ onSwitchShowCard: () => void;
+}) {
+ const { audioId, order, playQueue, showCard, switchSongByDiff, setOrder, setShowCard } = useAudioStore(
useShallow((state) => {
return {
audioId: state.audioId,
order: state.order,
playQueue: state.playQueue,
+ showCard: state.showCard,
setOrder: state.setOrder,
switchSongByDiff: state.switchSongByDiff,
+ setShowCard: state.setShowCard,
};
}),
);
@@ -127,6 +135,7 @@ export default function AudioPlayer({ className }: { className?: string }) {
order={order}
audio={audio}
duration={duration}
+ showCard={showCard}
onPlay={handlePlay}
onPrev={() => handleSwitchAudio(-1)}
onNext={() => handleSwitchAudio(1)}
@@ -134,6 +143,7 @@ export default function AudioPlayer({ className }: { className?: string }) {
className={className}
trackProgress={trackProgress}
onChangeProgress={handleChangeProgress}
+ onSwitchShowCard={onSwitchShowCard}
/>
);
}
diff --git a/src/components/AudioPlayer/PlayerBar.tsx b/src/components/AudioPlayer/PlayerBar.tsx
index b267478..21a99f5 100644
--- a/src/components/AudioPlayer/PlayerBar.tsx
+++ b/src/components/AudioPlayer/PlayerBar.tsx
@@ -3,12 +3,32 @@
import { useEffect } from 'react';
import dynamic from 'next/dynamic';
+import { useShallow } from 'zustand/react/shallow';
import Player from './Player';
+import PlayerCard from './PlayerCard';
-// import { debounce } from 'lodash';
+import useAudioStore from '@/store/audio';
const PlayerBar = ({ className }: { className?: string }) => {
+ const { audioId, order, playQueue, showCard, switchSongByDiff, setOrder, setShowCard } = useAudioStore(
+ useShallow((state) => {
+ return {
+ audioId: state.audioId,
+ order: state.order,
+ playQueue: state.playQueue,
+ showCard: state.showCard,
+ setOrder: state.setOrder,
+ switchSongByDiff: state.switchSongByDiff,
+ setShowCard: state.setShowCard,
+ };
+ }),
+ );
+
+ const handleSwitchShowCard = () => {
+ setShowCard(!showCard);
+ };
+
// let oldScrollY: number = 0;
// function handleScroll() {
// if (window.scrollY > oldScrollY) {
@@ -23,6 +43,13 @@ const PlayerBar = ({ className }: { className?: string }) => {
// oldScrollY = window.scrollY;
// }
+ useEffect(() => {
+ // window.addEventListener('scroll', handleScroll);
+ // return () => {
+ // window.removeEventListener('scroll', handleScroll);
+ // };
+ }, []);
+
useEffect(() => {
// window.addEventListener('scroll', handleScroll);
// return () => {
@@ -42,9 +69,12 @@ const PlayerBar = ({ className }: { className?: string }) => {
className={`fixed w-[100vw] h-[130px] bg-[#fff] shadow-lg shadow-black-[0_0_10px] z-10 ${className}`}
style={{ bottom: 0 }}
>
-
-
+ {/* 播放器 */}
+
+ {/* 单曲卡片 */}
+
);
};
diff --git a/src/components/AudioPlayer/PlayerCard.tsx b/src/components/AudioPlayer/PlayerCard.tsx
new file mode 100644
index 0000000..cecfcb8
--- /dev/null
+++ b/src/components/AudioPlayer/PlayerCard.tsx
@@ -0,0 +1,82 @@
+import Image from 'next/image';
+import { useShallow } from 'zustand/react/shallow';
+
+import styles from './index.module.css';
+
+import { SongCardList } from '@/components';
+import useAudioStore from '@/store/audio';
+
+interface Prop {
+ // onClose: () => void;
+ show: boolean;
+ className?: string;
+}
+
+export default function PlayerCard({ show, className }: Prop) {
+ const { audioId, playQueue } = useAudioStore(
+ useShallow((state) => {
+ return {
+ audioId: state.audioId,
+ playQueue: state.playQueue,
+ };
+ }),
+ );
+
+ const miniClass = 'w-100vw translate-y-100vh'; // 缩小时的样式
+ const largeClass = 'w-[100vw] translate-y-[-130px]'; // 放大后的样式
+
+ const audioInfo = playQueue.find((item) => item.id === audioId);
+
+ console.log(audioInfo);
+
+ return (
+
+
+ {/* 单曲信息 */}
+
+ {/* 专辑封面 */}
+ {/* 阴影 */}
+
+
+ {audioInfo?.pic && (
+
+ )}
+
+
+
+ {/* 歌曲名 */}
+
{audioInfo?.title ?? ''}
+ {/* 歌手/专辑 */}
+ {audioInfo?.artist && audioInfo?.album && (
+
{`${audioInfo.artist}/${audioInfo.album}`}
+ )}
+ {/* 歌词 */}
+
{audioInfo?.lrc ?
:
暂无歌词
}
+
+
+ {/* 播放列表 */}
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/AudioPlayer/PlayerControl.tsx b/src/components/AudioPlayer/PlayerControl.tsx
index 8efddae..ebfe27d 100644
--- a/src/components/AudioPlayer/PlayerControl.tsx
+++ b/src/components/AudioPlayer/PlayerControl.tsx
@@ -1,5 +1,7 @@
'use client';
+// 样式层
+
import Image from 'next/image';
import { secondToDate } from '@/utils/time';
@@ -12,6 +14,8 @@ interface Props {
audio: SongInfo | null;
order: PlayOrder;
playStatus: boolean;
+ showCard: boolean;
+ onSwitchShowCard: () => void;
onPlay: () => void;
onOrder: () => void;
onPrev: () => void;
@@ -26,11 +30,13 @@ export default function AudioPlayer({
audio,
order,
playStatus,
+ showCard,
onPlay,
onOrder,
onPrev,
onNext,
onChangeProgress,
+ onSwitchShowCard,
trackProgress,
duration,
className,
@@ -51,7 +57,8 @@ export default function AudioPlayer({
{/* 专辑封面 */}
{audio?.pic && (
diff --git a/src/components/AudioPlayer/index.module.css b/src/components/AudioPlayer/index.module.css
index 8bca1de..20cbc9e 100644
--- a/src/components/AudioPlayer/index.module.css
+++ b/src/components/AudioPlayer/index.module.css
@@ -24,6 +24,13 @@
background-size: 28px;
}
+/* 专辑封面 阴影 */
+.album_shoadow {
+ background: rgba(0, 0, 0, 0.08);
+ box-shadow: 27px 10px 30px -12px rgba(0, 0, 0, 0.25);
+ border-radius: 3px;
+}
+
.range-input {
-webkit-appearance: none;
width: 100%;
diff --git a/src/store/audio.ts b/src/store/audio.ts
index b4c8f0e..94271b6 100644
--- a/src/store/audio.ts
+++ b/src/store/audio.ts
@@ -12,7 +12,11 @@ interface AuioState {
order: PlayOrder;
/** 播放器显示状态 */
show: boolean;
+ /** 单曲卡牌展示 */
+ showCard: boolean;
+ /** 当前音频id */
audioId: string;
+ audioInfo: SongInfo | null;
/** 歌单列表 */
playList: SongInfo[];
/** 播放队列 */
@@ -21,6 +25,8 @@ interface AuioState {
setAudioId: (id: string) => void;
// 显示/隐藏播放器
setShow: (value: boolean) => void;
+ // 显示/隐藏单曲卡片
+ setShowCard: (value: boolean) => void;
// 设置播放列表
setPlayList: (params: { id: string; list: SongInfo[] }) => void;
// 切换歌曲 -1: 上一首 1: 下一首
@@ -94,9 +100,11 @@ const useAuioState = create
()(
order: 'list_loop',
playStatus: false,
show: false,
+ showCard: false,
playListId: '',
playList: [],
playQueue: [],
+ audioInfo: get()?.playList.length ? get().playList.find((item) => item.id === get().audioId) : null,
setAudioId,
setOrder,
setShow: (value) =>
@@ -105,6 +113,12 @@ const useAuioState = create()(
state.show = value;
}),
),
+ setShowCard: (value) =>
+ set(
+ produce((state) => {
+ state.showCard = value;
+ }),
+ ),
setPlayList: (params) => {
set(
produce((state) => {