手把手教你10分钟做一个音乐播放器

缺乏、安全感 2022-10-16 08:43 441阅读 0赞

一.话不多,先看效果:

视频B站效果演示地址~

 (大佬勿入,大佬勿入,大佬勿入)这是个单页面音乐播放器,只用到了 html+css 与很基础的vue语法,所以适合初学者,看一看10分钟就会了~

这个思路是借鉴黑马的~

二.详细制作步骤(完整代码在最后):

1.第一步当然是定义标签,对于每一个标签的作用注释都写得清清楚楚啦~:

  1. <!-- 最底层的盒子 -->
  2. <div class="container" id="container">
  3. <!-- 头部区域盒子 -->
  4. <div class="top">
  5. <!-- 搜索框 -->
  6. <input type="text" class="txt" v-model='query' @keyup.enter="searchMusic">
  7. </div>
  8. <!-- 歌曲列表区域 -->
  9. <div class="list">
  10. <ul>
  11. <!-- 每个li是一首歌 -->
  12. <li v-for="(item,index) in musicList " :key="index">
  13. <a href="javascript:;" @click="playMusic(item.id)"></a>
  14. {
  15. {item.name}}
  16. </li>
  17. </ul>
  18. </div>
  19. <!-- 中间区域 -->
  20. <div class="middle">
  21. <!-- 那个旋转的杆 -->
  22. <img src="img/player_bar.png" alt="x" class="bar" :class="{playing:isPlay}">
  23. <!-- 唱片 -->
  24. <img src="img/disc.png" alt="x" class="disk" :class="{turn:isPlay}">
  25. <!-- 唱片中间的海报 -->
  26. <img :src="poster" class="poster">
  27. </div>
  28. <!-- 评论区 -->
  29. <h5 class="commentTxt">热门评论:</h5>
  30. <div class="comment">
  31. <ul>
  32. <!-- 每条评论 -->
  33. <li v-for="(item,index) in comment" :key="index">
  34. <!-- 头像 -->
  35. <img :src="item.user.avatarUrl" alt="" width="50px" height="50px">
  36. <!-- 网名 -->
  37. <h3>{
  38. {item.user.nickname}}</h3>
  39. <!-- 评论内容 -->
  40. <p> {
  41. {item.content}}</p>
  42. </li>
  43. </ul>
  44. </div>
  45. <!-- 播放器进度条 -->
  46. <audio class="music" @play="play" @pause="pause" :src="url" controls autoplay loop></audio>
  47. </div>

标签里的vue语法解释(先看后面的js部分再看这里更好理解):

  1. <input type="text" class="txt" v-model='query' @keyup.enter="searchMusic">

给这个标签 v-model=’query’双向绑定数据query,@keyup.enter=”searchMusic”绑定键盘回车事件,触发searMusic函数。

  1. {
  2. {item.name}}

放内容,写在{ {}}里。item相对于变量。

  1. <li v-for="(item,index) in musicList " :key="index">

v-for=”” 根据 musicList这个数组里元素的数量,动态生成多少个 li 。

  1. <a href="javascript:;" @click="playMusic(item.id)"></a>

@click=”playMusic(item.id)点击事件,触发playMusic(item.id)函数,并传参数。

  1. <img src="img/player_bar.png" alt="x" class="bar" :class="{playing:isPlay}">

:class=”{playing:isPlay},若isPlay值为真,playing这个选择器生效。

  1. <img :src="poster" class="poster">

:src=”poster”地址的值为自己定义的变量poster。

后面都是相似的了,以此类推~

2.定义css部分,对一些不常见的属性都会解释~:

1.整体区域:
  1. /* 整体 */
  2. .container{
  3. width: 800px;
  4. height: 500px;
  5. background-color: rgba(248, 250, 252,0.3);
  6. border-radius: 10px;
  7. position: relative;
  8. overflow: hidden;
  9. }

border-radius: 10px; 角弧度
overflow: hidden;溢出隐藏

2.头部区域:
  1. /* 头部 */
  2. .top{
  3. position: absolute;
  4. top: 0;
  5. left: 0;
  6. width: 100%;
  7. height: 60px;
  8. border-radius: 10px 10px 0 0;
  9. background-image: linear-gradient(45deg,rgb(99, 202, 243),rgb(9, 253, 180),rgb(40, 106, 230));
  10. z-index: 11;
  11. }
  12. .txt{
  13. position: absolute;
  14. top: 15px;
  15. right: 50px;
  16. width: 200px;
  17. height: 30px;
  18. outline: none;
  19. border-radius: 15px;
  20. border: none;
  21. background-color: rgba(255, 255, 255,0.8);
  22. padding: 0 20px 0 20px;
  23. font-size: 13px;
  24. }

background-image: linear-gradient(45deg,rgb(99, 202, 243),rgb(9, 253, 180),rgb(40, 106, 230));渐变背景色。
z-index: 11; 显示的级别,就是防止被别的元素遮挡,越大越上
border: none; 取消边框

3. 歌曲列表部分:
  1. /* 歌曲列表 */
  2. .list{
  3. position: absolute;
  4. left: 0;
  5. top: 60px;
  6. width: 200px;
  7. height: 410px;
  8. background-color: rgba(255, 255, 255,0.5);
  9. }
  10. .list>ul{
  11. position: absolute;
  12. width: 100%;
  13. height: 100%;
  14. overflow: auto;
  15. }
  16. .list>ul>li{
  17. position: relative;
  18. width: 100%;
  19. height: 40px;
  20. line-height: 40px;
  21. font-family: 'fangsong';
  22. font-size: 16px;
  23. margin-top: 1px;
  24. padding-left: 30px;
  25. background-color: rgba(255, 255, 255, 0.9);
  26. }
  27. .list>ul>li>a{
  28. position: absolute;
  29. top: 50%;
  30. left: 5px;
  31. transform: translateY(-50%);
  32. width: 20px;
  33. height: 20px;
  34. background-image: url(img/play.png);
  35. background-size: 100% 100%;
  36. }

overflow: auto;如果内容被修剪,则浏览器会显示滚动条以便查看其余的内容。
transform: translateY(-50%); 偏移,通常在定位50%后再偏移自身大小50%达到居中效果。

4. 中间部分:
  1. /* 中间部分 */
  2. .middle{
  3. position: absolute;
  4. left: 210px;
  5. top: 60px;
  6. width: 410px;
  7. height: 410px;
  8. }
  9. .disk{
  10. position: absolute;
  11. width: 280px;
  12. height: 280px;
  13. left: 50%;
  14. top: 50%;
  15. transform: translate(-50%,-50%) rotateZ(0deg);
  16. }
  17. .bar{
  18. position: absolute;
  19. top: -10px;
  20. left: 50%;
  21. z-index:10;
  22. transform-origin: 10px 10px;
  23. /* 10 -25 */
  24. transform: rotateZ(-25deg);
  25. transition: all 1s;
  26. }
  27. .poster{
  28. position: absolute;
  29. top: 50%;
  30. left: 50%;
  31. transform: translate(-50%,-50%);
  32. width: 160px;
  33. height: 160px;
  34. border-radius: 50%;
  35. object-fit: cover;
  36. }

transform: translate(-50%,-50%) rotateZ(0deg); translate(-50%,-50%)表偏移, rotateZ(0deg)表旋转。
transform-origin: 10px 10px; 旋转点就是绕哪个点旋转。
transition: all 1s; 过渡效果。
object-fit: cover; 保持图片原有尺寸比例。但部分内容可能被剪切。

5.评论区:
  1. /* 评论 */
  2. .comment{
  3. position: absolute;
  4. top: 80px;
  5. right: -20px;
  6. height: 410px;
  7. width: 230px;
  8. overflow: auto;
  9. background-color: rgba(255, 255, 255,.4);
  10. border-top-left-radius: 15px;
  11. }
  12. .commentTxt{
  13. position: absolute;
  14. top: 60px;
  15. right: 110px;
  16. width: 100px;
  17. height: 20px;
  18. line-height: 20px;
  19. font-size: 12px;
  20. color: rgb(0, 0, 0);
  21. }
  22. .comment>ul>li{
  23. width: 210px;
  24. min-height: 50px;
  25. margin-top: 10px;
  26. font-size: 13px;
  27. padding: 5px;
  28. text-align:justify;
  29. }
  30. .comment>ul>li>img{
  31. border-radius: 50%;
  32. display: inline-block;
  33. vertical-align: middle;
  34. }
  35. .comment>ul>li>h3{
  36. display: inline-block;
  37. padding-left: 5px;
  38. }
  39. .comment>ul>li>p{
  40. padding-top: 6px;
  41. display: block;
  42. text-indent: 2em;
  43. }

vertical-align: middle;该属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐。
text-indent: 2em;将段落的第一行缩进xxx像素:

6. 播放器进度条部分:
  1. /* 进度条 */
  2. .music{
  3. position: absolute;
  4. bottom: 0px;
  5. left:0px;
  6. width: 800px;
  7. height: 34px;
  8. outline: none;
  9. background-color: rgb(241, 243, 244);
  10. }
7. 杆和唱片转动
  1. /* 杆和唱片转动 */
  2. .playing{
  3. transform: rotateZ(10deg);
  4. }
  5. .turn{
  6. animation:turn 3s linear infinite;
  7. }
  8. @keyframes turn{
  9. 0%{
  10. transform: translate(-50%,-50%) rotateZ(0deg);
  11. }
  12. 100%{
  13. transform: translate(-50%,-50%) rotateZ(360deg);
  14. }
  15. }

3. js部分,用vue语法写

1.先引入:
  1. <!-- 开发环境版本,包含了有帮助的命令行警告 -->
  2. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  3. <!-- 官网提供的 axios 在线地址 -->
  4. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
2.开始(详细请看注释):

歌曲主要调用的是网易云的公开API所得~

  1. new Vue({
  2. el:"#container",
  3. data(){
  4. return{
  5. //搜索关键字
  6. query:'',
  7. //歌曲列表
  8. musicList:[],
  9. //当前歌曲地址
  10. url:'',
  11. //海报地址
  12. poster:'./img/timg4.jpg',
  13. //判断是否正在播放
  14. isPlay: false,
  15. //评论
  16. comment:[]
  17. }
  18. },
  19. methods:{
  20. searchMusic(){
  21. // 判断搜索框有没有字
  22. if(this.query==''){
  23. //没有自己返回
  24. return;
  25. }
  26. // 发送请求获得数据
  27. axios({
  28. url:'https://autumnfish.cn/search',
  29. method:'get',
  30. params:{
  31. keywords:this.query
  32. }
  33. }).then(res=>{
  34. //把获取数据传给musicList数组,可以通过 console.log(res);查看自己想要的数据
  35. this.musicList = res.data.result.songs;
  36. })
  37. },
  38. playMusic(id){
  39. //获得歌曲的url
  40. axios({
  41. url:'https://autumnfish.cn/song/url',
  42. method:'get',
  43. params:{
  44. id:id
  45. }
  46. }).then(res=>{
  47. // 将当前歌曲地址设置为这个
  48. this.url = res.data.data[0].url;
  49. })
  50. //获取歌曲海豹
  51. axios({
  52. url:'https://autumnfish.cn/song/detail',
  53. method:'get',
  54. params:{
  55. ids:id
  56. }
  57. }).then(res=>{
  58. // 把图片地址纯存在poster数组
  59. this.poster=res.data.songs[0].al.picUrl
  60. })
  61. //获取评论
  62. axios({
  63. url:'https://autumnfish.cn/comment/hot',
  64. method:'get',
  65. params:{
  66. type:0,
  67. id:id
  68. }
  69. }).then(res=>{
  70. // 把评论的数据存在comment数组,包括头像,网名等等,可以通过 console.log(res);查看自己想要的数据
  71. this.comment=res.data.hotComments
  72. })
  73. },
  74. // 歌曲是正在播放触发
  75. play(){
  76. this.isPlay = true;
  77. },
  78. // 歌曲是停止触发
  79. pause(){
  80. this.isPlay = false;
  81. }
  82. }
  83. })

三. 完整代码(需要素材与源文件的私信或在评论区留下邮箱,我发你呀):

  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>music</title>
  8. <style> *{ margin: 0; padding: 0; box-sizing: border-box; } body{ height: 100vh; display: flex; justify-content: center; align-items: center; } /* 背景图 */ .bj{ position: fixed; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; z-index: -1000; } /* 整体 */ .container{ width: 800px; height: 500px; background-color: rgba(248, 250, 252,0.3); border-radius: 10px; position: relative; overflow: hidden; } /* 头部 */ .top{ position: absolute; top: 0; left: 0; width: 100%; height: 60px; border-radius: 10px 10px 0 0; background-image: linear-gradient(45deg,rgb(99, 202, 243),rgb(9, 253, 180),rgb(40, 106, 230)); z-index: 11; } .txt{ position: absolute; top: 15px; right: 50px; width: 200px; height: 30px; outline: none; border-radius: 15px; border: none; background-color: rgba(255, 255, 255,0.8); padding: 0 20px 0 20px; font-size: 13px; } /* 歌曲列表 */ .list{ position: absolute; left: 0; top: 60px; width: 200px; height: 410px; background-color: rgba(255, 255, 255,0.5); } .list>ul{ position: absolute; width: 100%; height: 100%; overflow: auto; } .list>ul>li{ position: relative; width: 100%; height: 40px; line-height: 40px; font-family: 'fangsong'; font-size: 16px; margin-top: 1px; padding-left: 30px; background-color: rgba(255, 255, 255, 0.9); } .list>ul>li>a{ position: absolute; top: 50%; left: 5px; transform: translateY(-50%); width: 20px; height: 20px; background-image: url(img/play.png); background-size: 100% 100%; } /* 中间部分 */ .middle{ position: absolute; left: 210px; top: 60px; width: 410px; height: 410px; } .disk{ position: absolute; width: 280px; height: 280px; left: 50%; top: 50%; transform: translate(-50%,-50%) rotateZ(0deg); } .bar{ position: absolute; top: -10px; left: 50%; z-index:10; transform-origin: 10px 10px; /* 10 -25 */ transform: rotateZ(-25deg); transition: all 1s; } .poster{ position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); width: 160px; height: 160px; border-radius: 50%; object-fit: cover; } /* 评论 */ .comment{ position: absolute; top: 80px; right: -20px; height: 410px; width: 230px; overflow: auto; background-color: rgba(255, 255, 255,.4); border-top-left-radius: 15px; } .commentTxt{ position: absolute; top: 60px; right: 110px; width: 100px; height: 20px; line-height: 20px; font-size: 12px; color: rgb(0, 0, 0); } .comment>ul>li{ width: 210px; min-height: 50px; margin-top: 10px; font-size: 13px; padding: 5px; text-align:justify; } .comment>ul>li>img{ border-radius: 50%; display: inline-block; vertical-align: middle; } .comment>ul>li>h3{ display: inline-block; padding-left: 5px; } .comment>ul>li>p{ padding-top: 6px; display: block; text-indent: 2em; } /* 进度条 */ .music{ position: absolute; bottom: 0px; left:0px; width: 800px; height: 34px; outline: none; background-color: rgb(241, 243, 244); } /* 杆和唱片转动 */ .playing{ transform: rotateZ(10deg); } .turn{ animation:turn 3s linear infinite; } @keyframes turn{ 0%{ transform: translate(-50%,-50%) rotateZ(0deg); } 100%{ transform: translate(-50%,-50%) rotateZ(360deg); } } </style>
  9. </head>
  10. <body>
  11. <video src="./video.mp4" class="bj" muted autoplay loop ></video>
  12. <div class="container" id="container">
  13. <!-- 头部 -->
  14. <div class="top">
  15. <input type="text" class="txt" v-model='query' @keyup.enter="searchMusic">
  16. </div>
  17. <div class="list">
  18. <ul>
  19. <li v-for="(item,index) in musicList " :key="index">
  20. <a href="javascript:;" @click="playMusic(item.id)"></a>
  21. {
  22. {item.name}}
  23. </li>
  24. </ul>
  25. </div>
  26. <div class="middle">
  27. <!-- 杆 -->
  28. <img src="img/player_bar.png" alt="x" class="bar" :class="{playing:isPlay}">
  29. <!-- 唱片 -->
  30. <img src="img/disc.png" alt="x" class="disk" :class="{turn:isPlay}">
  31. <!-- 海报 -->
  32. <img :src="poster" class="poster">
  33. </div>
  34. <h5 class="commentTxt">热门评论:</h5>
  35. <div class="comment">
  36. <ul>
  37. <li v-for="(item,index) in comment" :key="index">
  38. <img :src="item.user.avatarUrl" alt="" width="50px" height="50px">
  39. <h3>{
  40. {item.user.nickname}}</h3>
  41. <p> {
  42. {item.content}}</p>
  43. </li>
  44. </ul>
  45. </div>
  46. <audio class="music" @play="play" @pause="pause" :src="url" controls autoplay loop></audio>
  47. </div>
  48. <!-- 开发环境版本,包含了有帮助的命令行警告 -->
  49. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  50. <!-- 官网提供的 axios 在线地址 -->
  51. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  52. <script> new Vue({ el:"#container", data(){ return{ //搜索关键字 query:'', //歌曲列表 musicList:[], //当前歌曲地址 url:'', //海报 poster:'./img/timg4.jpg', //判断是否正在播放 isPlay: false, //评论 comment:[] } }, methods:{ searchMusic(){ if(this.query==''){ return; } axios({ url:'https://autumnfish.cn/search', method:'get', params:{ keywords:this.query } }).then(res=>{ this.musicList = res.data.result.songs; }) }, playMusic(id){ axios({ url:'https://autumnfish.cn/song/url', method:'get', params:{ id:id } }).then(res=>{ this.url = res.data.data[0].url; }) axios({ url:'https://autumnfish.cn/song/detail', method:'get', params:{ ids:id } }).then(res=>{ this.poster=res.data.songs[0].al.picUrl }) axios({ url:'https://autumnfish.cn/comment/hot', method:'get', params:{ type:0, id:id } }).then(res=>{ this.comment=res.data.hotComments }) }, play(){ this.isPlay = true; }, pause(){ this.isPlay = false; } } }) </script>
  53. </body>
  54. </html>

四.总结:

这样子就完成了~
再说一遍,需要素材与源文件的私信或在评论区留下你的邮箱,我发你呀,可以对比源码和文章注释学习~
对了,夏目友人帐大家看了吗,又被治愈了~
在这里插入图片描述

其它:

在这里插入图片描述

文字烟雾效果 html+css+js
环绕倒影加载特效 html+css
气泡浮动背景特效 html+css
简约时钟特效 html+css+js
赛博朋克风格按钮 html+css
仿网易云官网轮播图 html+css+js
水波加载动画 html+css
导航栏滚动渐变效果 html+css+js
书本翻页 html+css
3D立体相册 html+css
霓虹灯绘画板效果 html+css+js
记一些css属性总结(一)
Sass总结笔记
…等等
进我主页看更多~

发表评论

表情:
评论列表 (有 0 条评论,441人围观)

还没有评论,来说两句吧...

相关阅读

    相关 手把手一个脚手架

    最近在学习 vue-cli\[1\] 的源码,获益良多。为了让自己理解得更加深刻,我决定模仿它造一个轮子,争取尽可能多的实现原有的功能。 我将这个轮子分成三个版本: 1.尽