音乐播放器
https://spacexcode.com/player
那女孩对我说
心很空 天很大 云很重 我很孤单
00:00
-00:00
介绍
这是为自己制作的一个在线 Web 版的音乐播放器。众所周知,现在市面上的所有的音乐平台都是会员制。而免费的资源却分散在网络上的各个角落,为此,我收集了自己 喜欢的音乐,放到自己的服务器上,并制作了这样一个专属歌单的简单的音乐播放器。
实现讲解
该播放器虽然简单,但也是五脏俱全,该有的功能一个都没少。比如常见的音乐播放器,我们能想到的功能有:
- 暂停/开始播放按键
- 调节播放进度的进度条
- 调节声音大小的按键
- 切换下一首/上一首按键
- 查看歌单的界面
界面
如果不考虑界面, Web 端的音频播放有现成的标签 audio
支持
<audio controls src="https://spacexcode.oss-cn-hangzhou.aliyuncs.com/mp3/那女孩对我说.mp3" />
这是浏览器渲染的默认样式,各个浏览器可能会有差异。我们要实现一个音乐播放器,当然要所有端的样式统一。这个时候,我们就移除 controls
属性,让
实际的播放组件在页面上什么都不显示。然后我们自己去实现上面的所有控件。
由于这个站点引入的是 Material UI,为了统一视觉,就使用里面现成的组件去实现。
实时编辑器
function player () { const [paused, setPaused] = React.useState(true); return ( <Box sx={{ width: '100%', overflow: 'hidden' }}> <div style={{ padding: 16, borderRadius: 16, width: 343, maxWidth: '100%', margin: 'auto', position: 'relative', zIndex: 1, backgroundColor: 'rgba(255,255,255,0.4)', backdropFilter: 'blur(40px)' }}> <Box sx={{ display: 'flex', alignItems: 'center', position: 'relative' }}> <div style={{ width: 100, height: 100, objectFit: 'cover', overflow: 'hidden', flexShrink: 0, borderRadius: 8, backgroundColor: 'rgba(0,0,0,0.08)', '& > img': { width: '100%', } }}> <img alt='那女孩对我说' src='https://spacexcode.oss-cn-hangzhou.aliyuncs.com/1697270523238-8b4b11a5-b5a3-4ac3-b6bd-1e264f526c76.png' /> </div> <Box sx={{ position: 'absolute', top: 0, right: 0 }}> <IconButton aria-label="music queue"> <QueueMusicIcon fontSize="small" htmlColor='rgba(0,0,0,0.4)' /> </IconButton> </Box> <Box sx={{ ml: 1.5, minWidth: 0 }}> <Typography variant="caption" color="text.secondary" fontWeight={500}> 林俊杰 </Typography> <Typography noWrap> <b>那女孩对我说</b> </Typography> <Typography noWrap letterSpacing={-0.25}> 心很空 天很大 云很重 我很孤单 </Typography> </Box> </Box> <Slider aria-label="time-indicator" size="small" value={30} min={0} step={1} max={405} sx={{ color: 'rgba(0,0,0,0.87)', height: 4, '& .MuiSlider-thumb': { width: 8, height: 8, transition: '0.3s cubic-bezier(.47,1.64,.41,.8)', '&:before': { boxShadow: '0 2px 12px 0 rgba(0,0,0,0.4)', }, '&:hover, &.Mui-focusVisible': { boxShadow: `0px 0px 0px 8px ${ 'rgb(0 0 0 / 16%)' }`, }, '&.Mui-active': { width: 20, height: 20, }, }, '& .MuiSlider-rail': { opacity: 0.28, }, }} /> <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mt: -2 }} > <div style={{ fontSize: '0.75rem', opacity: 0.38, fontWeight: 500, letterSpacing: 0.2 }}>00:30</div> <div style={{ fontSize: '0.75rem', opacity: 0.38, fontWeight: 500, letterSpacing: 0.2 }}>-04:00</div> </Box> <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center', mt: -1 }} > <audio src='https://spacexcode.oss-cn-hangzhou.aliyuncs.com/mp3/那女孩对我说.mp3' /> <IconButton aria-label="previous song"> <FastRewindRounded fontSize="large" htmlColor='#000' /> </IconButton> <IconButton aria-label='pause'> <PauseRounded sx={{ fontSize: '3rem' }} htmlColor='#000' /> </IconButton> <IconButton aria-label="next song"> <FastForwardRounded fontSize="large" htmlColor='#000' /> </IconButton> </Box> <Stack spacing={2} direction="row" sx={{ mb: 1, px: 1 }} alignItems="center"> <VolumeDownRounded htmlColor='rgba(0,0,0,0.4)' /> <Slider aria-label="Volume" value={0.3} min={0} step={0.01} max={1} sx={{ color: 'rgba(0,0,0,0.87)', '& .MuiSlider-track': { border: 'none', }, '& .MuiSlider-thumb': { width: 16, height: 16, backgroundColor: '#fff', '&:before': { boxShadow: '0 4px 8px rgba(0,0,0,0.4)', }, '&:hover, &.Mui-focusVisible, &.Mui-active': { boxShadow: 'none', }, }, }} /> <VolumeUpRounded htmlColor='rgba(0,0,0,0.4)' /> </Stack> </div> </Box> ) }
结果
Loading...
至此以上代码,初步实现了基本的播放器界面,然后我们需要对每个功能控件添加事件实现它应该有的功能。
播放按钮
控制播放器的播放,我们可以通过 audio
提供的 play()
和 pause()
接口,首先我们使用 useRef
获取音频组件的实例,然后通过判断
当前的播放状态,调用播放和暂停接口。
function Player () {
const audioPlayer = useRef();
const [paused, setPaused] = useState(true);
const onPlayOrPause = () => {
paused ? audioPlayer.current.play() : audioPlayer.current.pause();
setPaused(!paused)
}
}
下面所有使用的变量
audioPlayer
代表获取的<audio ref="audioPlayer" />
播放器实例
调节进度
在 Slider
组件上绑定 onChange
事件,此时 Slider
组件中的最大值即为该音频资源的最大时长。回调中拿到设置的进度值后赋值给 currentTime
属性。
const [position, setPosition] = useState(0); // 表示当前的播放进度值
const onChangeProgress = (val) => {
setPosition(val);
audioPlayer.current.currentTime = val;
}