【小程序】实现一个定制的音乐播放器

8a941a1295752c7ba2966d4a38f83839.png

应用地址:https://spacexcode.com/player

介绍

这是为自己制作的一个在线 Web 版的音乐播放器。众所周知,现在市面上的所有的音乐平台都是会员制。而免费的资源却分散在网络上的各个角落,为此,我收集了自己 喜欢的音乐,放到自己的服务器上,并制作了这样一个专属歌单的简单的音乐播放器。

实现讲解

该播放器虽然简单,但也是五脏俱全,该有的功能一个都没少。比如常见的音乐播放器,我们能想到的功能有:

  • 暂停/开始播放按键

  • 调节播放进度的进度条

  • 调节声音大小的按键

  • 切换下一首/上一首按键

  • 查看歌单的界面

界面

如果不考虑界面, Web 端的音频播放有现成的标签 audio 支持

<audio controls src="https://spacexcode.oss-cn-hangzhou.aliyuncs.com/mp3/那女孩对我说.mp3" />
8e382cf0d9905149be535d735f71b5da.png

这是浏览器渲染的默认样式,各个浏览器可能会有差异。我们要实现一个音乐播放器,当然要所有端的样式统一。这个时候,我们就移除 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>)
}
631352b68166a0eac2ce60cf0275accc.png

至此以上代码,初步实现了基本的播放器界面,然后我们需要对每个功能控件添加事件实现它应该有的功能。

播放按钮

控制播放器的播放,我们可以通过 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;
}

这个音频的资源时长,可以通过监听资源加载完成事件,通过 duration 属性获取。它单位为**毫秒(ms)**。

audioPlayer.current.addEventListener('loadeddata', () => {setDuration(audioPlayer.current?.duration)
});

调节音量

音量的调节和进度同样使用的是 Slider 组件,不过它的最大值为 1,步长为 0.01

改变音量时,将获取到的音量值赋给 audioPlayer 实例的 volumn 属性。

const onChangeVolume = (val) => {setVolume(val);audioPlayer.current.volume = val;
};

切换歌单

切换上一首/下一首,无非就是改变当前播放的音频资源。该音频资源对应到资源列表的索引值,我们通过控制索引值去列表中获取不同的音乐素材。

这里要考虑边界值的情况,当切换的时候碰到最大值和最小值,如果允许循环,那么在索引值等于数组长度时,将它的值重置为 0

// 上一首
const onPreview = () => {if (currentIndex > 0) {changeCurrentIndex(currentIndex - 1); }
}// 下一首
const onNext = () => {if (currentIndex < songList.length - 1) {changeCurrentIndex(currentIndex + 1);} else {changeCurrentIndex(0);}
}

查看歌单

除了所有的功能按钮,右上角还有一个查看歌单的按钮,点击从底部弹出一个 drawer 抽屉组件。里面列出了一个收藏的音乐列表。

function MusicQueue() {const songList = [{artists: '林俊杰',name: '那女孩对我说',avatar: 'https://spacexcode.oss-cn-hangzhou.aliyuncs.com/1697270523238-8b4b11a5-b5a3-4ac3-b6bd-1e264f526c76.png',link: 'https://spacexcode.oss-cn-hangzhou.aliyuncs.com/mp3/那女孩对我说.mp3',lyric: '心很空 天很大 云很重 我很孤单'},{artists: '张靓颖',name: '终于等到你',avatar: 'https://spacexcode.oss-cn-hangzhou.aliyuncs.com/1697503257045-7a262b7d-0df0-4005-a69c-2a645ac24c27.png',link: 'https://spacexcode.oss-cn-hangzhou.aliyuncs.com/mp3/终于等到你-张靓颖.mp3',lyric: '到了某个年纪你就会知道 一个人的日子真的难熬'},{artists: '张靓颖',name: '饿狼传说',avatar: 'https://spacexcode.oss-cn-hangzhou.aliyuncs.com/1697503257045-7a262b7d-0df0-4005-a69c-2a645ac24c27.png',link: 'https://spacexcode.oss-cn-hangzhou.aliyuncs.com/mp3/饿狼传说-张靓颖.mp3',lyric: '她熄掉晚灯 幽幽掩两肩 交织了火花 拘禁在沉淀'}];return (<Box sx={{ width: 'auto' }} role="presentation"><List>{songList.map((item, index) => (<ListItemkey={index} disablePadding><ListItemButton><ListItemIcon><Avatar alt={item.artists} src={item.avatar} /></ListItemIcon><ListItemText secondary={<React.Fragment><Typography sx={{ display: 'inline' }} component="span" variant="body1" color="text.primary">{item.name}</Typography>{' -- ' + item.artists}</React.Fragment>} /></ListItemButton></ListItem>))}</List></Box>);
}
ab4da5ca5227a003db10c1bc4a386227.png

至此我们已经实现了界面上所有的控制按钮的功能。最后需要完善下一些边界和初始情况的处理。

当音频在播放的时候,进度条需要随着当前播放时间变化而变化。这里采用定时器,每隔一秒获取播放资源的当前播放时间点,同步给 Slider 组件的 value 属性来定位。

const [timer, setTimer] = useState(null);audioPlayer.current.addEventListener('play', () => {if (timer) {clearInterval(timer);}setTimer(setInterval(() => {setPosition(audioPlayer.current?.currentTime)}, 1000));
});
audioPlayer.current.addEventListener('pause', () => {if (timer) {clearInterval(timer);}
});

还有歌词的显示,下一步计划加上~

总结

实现一个定制的音乐播放器不复杂,控制功能的实现都有现成的接口:

  • 播放 play()

  • 暂停 pause()

  • 播放进度通过 currentTime 获取

  • 音量控制通过 volumn 的值控制

  • 音频的自动播放通过 autoplay 属性

  • 控制音频播放的时候为静音 muted

  • 当前音频资源循环播放通过属性 loop

我们需要考虑的是如何优化界面,毕竟一款颜值高的播放器和动听的音乐才能给我们带来内心的愉悦。

- END -

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/169163.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

选购采购管理软件,首先考虑这5个功能

虽然采购已经达到了数字化的临界点&#xff0c;但企业在接受新的解决方案时却犹豫不决。德勤一份全球首席采购官调查显示&#xff0c;只有 18% 的组织制定了数字化采购战略。 自动化采购任务和优化采购到付款周期可以为企业节省大量金钱和时间。然而&#xff0c;通过过时的采购…

JVM、JRE、JDK

JVM JVM&#xff08;Java Virtual Machine&#xff09;是Java虚拟机的缩写&#xff0c;他是Java编程语言运行时环境&#xff0c;负责执行Java字节码。另外作为JVM虚拟机&#xff0c;它在各种操作系统上提供统一的平台&#xff0c;这帮助Java应用程序可以独立于操作系统底层运行…

v-for列表渲染

一、v-for迭代数组 <li v-for"(e,index) in emp" :key"e.id">编号{{index1}} 名字{{e.name}} 年龄{{e.age}} </li> e 是循环数组中的每个元素的别名index 是当前循环的下表&#xff0c;从0开始:key 的作用&#xff1a; 是为了给 Vue 一个提示…

【AI视野·今日Sound 声学论文速览 第二十九期】Thu, 19 Oct 2023

AI视野今日CS.Sound 声学论文速览 Thu, 19 Oct 2023 Totally 9 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers Take the aTrain. Introducing an Interface for the Accessible Transcription of Interviews Authors Armin Haberl, J rgen Flei , Dom…

[C++] 类与对象(上)

☃️个人主页&#xff1a;fighting小泽 &#x1f338;作者简介&#xff1a;目前正在学习C和Linux &#x1f33c;博客专栏&#xff1a;C入门 &#x1f3f5;️欢迎关注&#xff1a;评论&#x1f44a;&#x1f3fb;点赞&#x1f44d;&#x1f3fb;留言&#x1f4aa;&#x1f3fb; …

设计模式篇---组合模式

文章目录 概念结构实例总结 概念 组合模式&#xff1a;组合多个对象形成树形结构以表示具有部分-整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象。 当我们开发中遇到树形结构的业务时&#xff0c;可以考虑使用组合模式。&#xff08;我也没有想明白为啥…

前端如何直接上传文件夹

前面写了一篇仿写el-upload组件&#xff0c;彻底搞懂文件上传&#xff0c;实现了选择/拖拽文件上传&#xff0c;我们经常看到一些网站支持直接选择整个文件夹上传&#xff0c;例如&#xff1a;宝塔面板、cloudflare托管、对象存储网站等等需要模拟文件路径存储文件的场景。那是…

px4仿真实现无人机自主飞行

一,确定消息类型 无人机通过即在电脑是现自主飞行:思路如下。 通过Mavros功能包,将ROS消息转换为Mavlink消息。实现对无人机的控制。 几种消息之间的关系如下: 对于ROS数据,就是我们机载电脑执行ROS系统的数据。 对于Mavros消息,就是Mavros功能包内部的消息。查询网站…

leetcode:575. 分糖果(python3解法)

难度&#xff1a;简单 Alice 有 n 枚糖&#xff0c;其中第 i 枚糖的类型为 candyType[i] 。Alice 注意到她的体重正在增长&#xff0c;所以前去拜访了一位医生。 医生建议 Alice 要少摄入糖分&#xff0c;只吃掉她所有糖的 n / 2 即可&#xff08;n 是一个偶数&#xff09;。Al…

《数字图像处理-OpenCV/Python》连载(26)绘制椭圆和椭圆弧

《数字图像处理-OpenCV/Python》连载&#xff08;26&#xff09;绘制椭圆和椭圆弧 本书京东优惠购书链接&#xff1a;https://item.jd.com/14098452.html 本书CSDN独家连载专栏&#xff1a;https://blog.csdn.net/youcans/category_12418787.html 第 4 章 绘图与鼠标交互 本章…

同心创变,共赢未来 ▏易我科技2023年度“春种秋收”经营分析会圆满举行

2023年10月12日—10月13日&#xff0c;易我科技举行了2023年度管理层秋季团建暨“春种秋收”经营分析会&#xff0c;全体管理干部参加了本次活动。 01 本次团建活动的主题是“同心创变&#xff0c;共赢未来”&#xff0c;旨在通过一系列有趣而富有挑战性的团队活动&#xff0c…

计算机能转嵌入式吗?

计算机能转嵌入式吗&#xff1f;计算机和嵌入式不是一个范畴的&#xff0c;嵌入式是计算机的一个求职方向或者细分领域。你应该把他和Java放在一个层次上而不是跟整个计算机放在一个层次上。最近很多小伙伴找我&#xff0c;说想要一些嵌入式资料&#xff0c;然后我根据自己从业…

Node编写用户注册接口

目录 前言 创建服务器 编写注册接口API 创建路由对象&#xff0c;将路由对象导出去 将路由对象导出到服务器中 判断用户发起注册请求时是否输入账号或密码 验证表单数据 在数据库中创建表 在node中绑定mysql数据库 判断用户注册的账号密码是否已经被注册 密码加密 完…

水质分析仪器升级新功能

水质分析仪器&#xff1a;是一种适用于水质多参数测试的便携式仪器。它具有7英寸的触摸彩色屏幕&#xff0c;用户可以通过触摸屏幕进行操作和查看测试结果。 该仪器主要用于测定COD&#xff0c;氨氮&#xff0c;总磷&#xff0c;总氮等常规水质指标&#xff0c;pH值、溶解氧、…

CVer从0入门NLP(一)———词向量与RNN模型

&#x1f34a;作者简介&#xff1a;秃头小苏&#xff0c;致力于用最通俗的语言描述问题 &#x1f34a;专栏推荐&#xff1a;深度学习网络原理与实战 &#x1f34a;近期目标&#xff1a;写好专栏的每一篇文章 &#x1f34a;支持小苏&#xff1a;点赞&#x1f44d;&#x1f3fc;、…

rancher2.6.4配置管理k8s,docker安装

docker快速安装rancher并管理当前k8s集群。 1、拉镜像 docker pull rancher/rancher:v2.6.4 2、启动rancher 启动很慢 --privileged必须拥有root权限&#xff0c;并挂载卷 docker run --privileged -d --restartunless-stopped -p 80:80 -p 443:443 -v /usr/local/docker_vo…

模拟经营微信小游戏-休闲餐厅上线了

《休闲餐厅》是一款关于餐厅经营的小游戏&#xff0c;玩家可以在游戏中扮演餐厅老板&#xff0c;经营自己的休闲餐厅&#xff0c;收集美丽的厨娘&#xff0c;炒菜、做饭、卖钱、装饰餐厅&#xff0c;享受经营的乐趣。 在游戏中&#xff0c;玩家可以解锁几百种菜品&#xff0c;每…

【JS的设计模式一】

本文参考书籍 《JavaScript设计模式与开发实践》 在 JavaScript 编程中&#xff0c;this 关键字总是让人感到迷惑&#xff0c;Function.prototype.call 和 Function.prototype.apply 这两个方法也有着广泛的运用。我们有必要在学习设计模式之前先理解 这几个概念。 this Java…

百度Comate代码助手全新上线SaaS服务,助力企业释放10倍软件生产力!

“1024”程序员节来临之际&#xff0c;百度智能云宣布百度Comate智能代码助手正式上线SaaS版本&#xff0c;可提供10余项编码功能&#xff0c;适配100种开发语言&#xff0c;面向广大企业和开发者提供更便捷、更灵活的智能编码工具&#xff0c;助力企业提升研发效率。即日起企业…

python控制Windows桌面程序自动化模块uiautomation

github仓库地址&#xff1a;GitHub - yinkaisheng/Python-UIAutomation-for-Windows: (Donot use 3.7.6,3.8.1):snake:Python 3 wrapper of Microsoft UIAutomation. Support UIAutomation for MFC, WindowsForm, WPF, Modern UI(Metro UI), Qt, IE, Firefox, Chrome ... uiaut…