Vue制作音乐播放器_基于网易云音乐的接口
参考:
https://www.bilibili.com/video/BV12J411m7MG
github 下载完整项目:
https://github.com/VicentWYS/Vue_MusicPlayer
核心:
Vue + axios 联合使用,axios用于发起get请求,从接口获取数据。
Vue框架使用,对从接口返回的数据(类似于DOM树的集合)进行选择,然后渲染到页面上。
项目启动方法:
1.启动IDEA
2.打开项目 – 已存在的项目
3.选择项目文件夹,点击确定
效果:
播放器页面:
MV播放页面:
vueMusicPlayer.html:
1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8" /> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge" /> 8 <title>悦听player</title> 9 <!-- 样式 --> 10 <link rel="stylesheet" href="./css/index.css"> 11 </head> 12 13 <body> 14 <div class="wrap"> 15 <!-- 播放器主体区域 --> 16 <div class="play_wrap" id="player"> 17 <div class="search_bar"> 18 <img src="images/player_title.png" alt="" /> 19 <!-- 搜索歌曲 --> 20 <input type="text" autocomplete="off" v-model="query" @keyup.enter="searchMusic" /> 21 </div> 22 <div class="center_con"> 23 <!-- 搜索歌曲列表 --> 24 <div class=\'song_wrapper\'> 25 <ul class="song_list"> 26 <li v-for="item in musicList"> 27 <a href="javascript:;" @click="playMusic(item.id)"></a> 28 <b>{{item.name}}</b> 29 <span v-if="item.mvid!=0" @click="playMV(item.mvid)"><i></i></span> 30 </li> 31 </ul> 32 <img src="images/line.png" class="switch_btn" alt=""> 33 </div> 34 <!-- 歌曲信息容器 --> 35 <div class="player_con" :class="{playing:isPlaying}"> 36 <img src="images/player_bar.png" class="play_bar" /> 37 <!-- 黑胶碟片 --> 38 <img src="images/disc.png" class="disc autoRotate" /> 39 <img class="cover autoRotate" :src="musicCover" /> 40 </div> 41 <!-- 评论容器 --> 42 <div class="comment_wrapper"> 43 <h5 class=\'title\'>热门留言</h5> 44 <div class=\'comment_list\'> 45 <dl v-for="item in hotComments"> 46 <dt><img :src="item.user.avatarUrl" alt=""></dt> 47 <dd class="name">{{item.user.nickname}}</dd> 48 <dd class="detail">{{item.content}}</dd> 49 </dl> 50 </div> 51 <img src="images/line.png" class="right_line"> 52 </div> 53 </div> 54 <!--播放面板--> 55 <div class="audio_con"> 56 <audio ref=\'audio\' @play="play" @pause="pause" :src="musicUrl" controls autoplay loop class="myaudio"></audio> 57 </div> 58 <div class="video_con" v-show="isShow" style="display: none;"> 59 <video :src="mvUrl" controls="controls"></video> 60 <div class="mask" @click="hide"></div> 61 </div> 62 </div> 63 </div> 64 <!-- 开发环境版本,包含了有帮助的命令行警告 --> 65 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 66 <!-- 官网提供的 axios 在线地址 --> 67 <script src="https://unpkg.com/axios/dist/axios.min.js"></script> 68 <script src="./js/main.js"></script> 69 </body> 70 71 </html>
View Code
main.js:
1 /* 2 歌曲搜索接口: 3 请求地址:https://autumnfish.cn/search 4 请求方法:get 5 请求参数:keywords(查询关键字) 6 响应内容:歌曲搜索结果 7 */ 8 9 /* 10 歌曲url获取接口 11 请求地址:https://autumnfish.cn/song/url 12 请求方法:get 13 请求参数:id(查询关键字) 14 响应内容:歌曲url地址 15 */ 16 17 /* 18 歌曲详情获取 19 请求地址:https://autumnfish.cn/song/detail 20 请求方法:get 21 请求参数:ids(歌曲id) 22 响应内容:歌曲详情(包括封面信息) 23 */ 24 25 /* 26 热门评论获取 27 请求地址:https://autumnfish.cn/comment/hot?type=0 28 请求方法:get 29 请求参数:id(歌曲id,地址中的type固定为0) 30 响应内容:歌曲的热门评论 31 */ 32 33 /* 34 mv地址获取 35 请求地址:https://autumnfish.cn/mv/url 36 请求方法:get 37 请求参数:id(mvid,为0表示没有mv) 38 响应内容:mv的地址 39 */ 40 41 var app = new Vue({ 42 el:\'#player\', 43 data:{ 44 // 查询关键字 45 query:"", 46 // 歌曲数组 47 musicList:[], 48 // 歌曲地址 49 musicUrl:"", 50 // 歌曲封面 51 musicCover:"", 52 // 歌曲评论 53 hotComments:[], 54 // 动画播放状态 55 isPlaying:false, 56 // 遮罩层的显示状态 57 isShow:false, 58 // mv地址 59 mvUrl:"" 60 }, 61 methods:{ 62 // 歌曲搜索 63 searchMusic:function () { 64 var that = this; 65 axios.get("https://autumnfish.cn/search?keywords=" + this.query) 66 .then(function (res) { 67 // console.log(res); 68 that.musicList = res.data.result.songs; 69 }, function (err) { 70 }) 71 }, 72 // 歌曲播放 73 playMusic:function (musicId) { 74 var that = this; 75 // 获取歌曲地址 76 axios.get("https://autumnfish.cn/song/url?id=" + musicId) 77 .then(function (res) { 78 that.musicUrl = res.data.data[0].url; 79 }, function (err) {}); 80 81 // 歌曲详情获取 82 axios.get("https://autumnfish.cn/song/detail?ids=" + musicId) 83 .then( 84 function (res) { 85 // console.log(res); 86 // console.log(res.data.songs[0].al.picUrl); 87 that.musicCover = res.data.songs[0].al.picUrl; 88 }, function (err) { } 89 ); 90 91 // 歌曲评论获取 92 axios.get("https://autumnfish.cn/comment/hot?type=0&id=" + musicId) 93 .then( 94 function (res) { 95 // console.log(res); 96 // console.log(res.data.hotComments); 97 that.hotComments = res.data.hotComments; 98 }, function (err) { } 99 ) 100 101 }, 102 // 歌曲播放 103 play:function () { 104 // console.log("play"); 105 this.isPlaying = true; 106 }, 107 // 歌曲暂停 108 pause:function () { 109 // console.log("pause"); 110 this.isPlaying = false; 111 }, 112 // 播放mv 113 playMV:function (mvid) { 114 var that = this; 115 // 获取MV地址 116 axios.get("https://autumnfish.cn/mv/url?id=" + mvid) 117 .then(function (res) { 118 // console.log(res.data.data.url); 119 // 显示遮罩层 120 that.isShow = true; 121 that.mvUrl = res.data.data.url; 122 }, function (err) {}); 123 }, 124 //隐藏遮罩层 125 hide:function () { 126 this.isShow = false; 127 } 128 } 129 });
View Code
index.css:
1 body, 2 ul, 3 dl, 4 dd { 5 margin: 0px; 6 padding: 0px; 7 } 8 9 .wrap { 10 position: fixed; 11 left: 0; 12 top: 0; 13 width: 100%; 14 height: 100%; 15 background: url("../images/bg.jpg") no-repeat; 16 background-size: 100% 100%; 17 } 18 19 .play_wrap { 20 width: 800px; 21 height: 544px; 22 position: fixed; 23 left: 50%; 24 top: 50%; 25 margin-left: -400px; 26 margin-top: -272px; 27 /* background-color: #f9f9f9; */ 28 } 29 30 .search_bar { 31 height: 60px; 32 background-color: #1eacda; 33 border-top-left-radius: 4px; 34 border-top-right-radius: 4px; 35 display: flex; 36 align-items: center; 37 justify-content: space-between; 38 position: relative; 39 z-index: 11; 40 } 41 42 .search_bar img { 43 margin-left: 23px; 44 } 45 46 .search_bar input { 47 margin-right: 23px; 48 width: 296px; 49 height: 34px; 50 border-radius: 17px; 51 border: 0px; 52 background: url("../images/zoom.png") 265px center no-repeat 53 rgba(255, 255, 255, 0.45); 54 text-indent: 15px; 55 outline: none; 56 } 57 58 .center_con { 59 height: 435px; 60 background-color: rgba(255, 255, 255, 0.5); 61 display: flex; 62 position: relative; 63 } 64 65 .song_wrapper { 66 width: 200px; 67 height: 435px; 68 box-sizing: border-box; 69 padding: 10px; 70 list-style: none; 71 position: absolute; 72 left: 0px; 73 top: 0px; 74 z-index: 1; 75 } 76 77 .song_stretch { 78 width: 600px; 79 } 80 81 .song_list { 82 width: 100%; 83 overflow-y: auto; 84 overflow-x: hidden; 85 height: 100%; 86 } 87 .song_list::-webkit-scrollbar { 88 display: none; 89 } 90 91 .song_list li { 92 font-size: 12px; 93 color: #333; 94 height: 40px; 95 display: flex; 96 flex-wrap: wrap; 97 align-items: center; 98 width: 580px; 99 padding-left: 10px; 100 } 101 102 .song_list li:nth-child(odd) { 103 background-color: rgba(240, 240, 240, 0.3); 104 } 105 106 .song_list li a { 107 display: block; 108 width: 17px; 109 height: 17px; 110 background-image: url("../images/play.png"); 111 background-size: 100%; 112 margin-right: 5px; 113 box-sizing: border-box; 114 } 115 116 .song_list li b { 117 font-weight: normal; 118 width: 122px; 119 overflow: hidden; 120 text-overflow: ellipsis; 121 white-space: nowrap; 122 } 123 124 .song_stretch .song_list li b { 125 width: 200px; 126 } 127 128 .song_stretch .song_list li em { 129 width: 150px; 130 } 131 132 .song_list li span { 133 width: 23px; 134 height: 17px; 135 margin-right: 50px; 136 } 137 .song_list li span i { 138 display: block; 139 width: 100%; 140 height: 100%; 141 cursor: pointer; 142 background: url("../images/table.png") left -48px no-repeat; 143 } 144 145 .song_list li em, 146 .song_list li i { 147 font-style: normal; 148 width: 100px; 149 } 150 151 .player_con { 152 width: 400px; 153 height: 435px; 154 position: absolute; 155 left: 200px; 156 top: 0px; 157 } 158 159 .player_con2 { 160 width: 400px; 161 height: 435px; 162 position: absolute; 163 left: 200px; 164 top: 0px; 165 } 166 167 .player_con2 video { 168 position: absolute; 169 left: 20px; 170 top: 30px; 171 width: 355px; 172 height: 265px; 173 } 174 175 .disc { 176 position: absolute; 177 left: 73px; 178 top: 60px; 179 z-index: 9; 180 } 181 .cover { 182 position: absolute; 183 left: 125px; 184 top: 112px; 185 width: 150px; 186 height: 150px; 187 border-radius: 75px; 188 z-index: 8; 189 } 190 .comment_wrapper { 191 width: 180px; 192 height: 435px; 193 list-style: none; 194 position: absolute; 195 left: 600px; 196 top: 0px; 197 padding: 25px 10px; 198 } 199 .comment_wrapper .title { 200 position: absolute; 201 top: 0; 202 margin-top: 10px; 203 } 204 .comment_wrapper .comment_list { 205 overflow: auto; 206 height: 410px; 207 } 208 .comment_wrapper .comment_list::-webkit-scrollbar { 209 display: none; 210 } 211 .comment_wrapper dl { 212 padding-top: 10px; 213 padding-left: 55px; 214 position: relative; 215 margin-bottom: 20px; 216 } 217 218 .comment_wrapper dt { 219 position: absolute; 220 left: 4px; 221 top: 10px; 222 } 223 224 .comment_wrapper dt img { 225 width: 40px; 226 height: 40px; 227 border-radius: 20px; 228 } 229 230 .comment_wrapper dd { 231 font-size: 12px; 232 } 233 234 .comment_wrapper .name { 235 font-weight: bold; 236 color: #333; 237 padding-top: 5px; 238 } 239 240 .comment_wrapper .detail { 241 color: #666; 242 margin-top: 5px; 243 line-height: 18px; 244 } 245 .audio_con { 246 height: 50px; 247 background-color: #f1f3f4; 248 border-bottom-left-radius: 4px; 249 border-bottom-right-radius: 4px; 250 } 251 .myaudio { 252 width: 800px; 253 height: 40px; 254 margin-top: 5px; 255 outline: none; 256 background-color: #f1f3f4; 257 } 258 /* 旋转的动画 */ 259 @keyframes Rotate { 260 from { 261 transform: rotateZ(0); 262 } 263 to { 264 transform: rotateZ(360deg); 265 } 266 } 267 /* 旋转的类名 */ 268 .autoRotate { 269 animation-name: Rotate; 270 animation-iteration-count: infinite; 271 animation-play-state: paused; 272 animation-timing-function: linear; 273 animation-duration: 5s; 274 } 275 /* 是否正在播放 */ 276 .player_con.playing .disc, 277 .player_con.playing .cover { 278 animation-play-state: running; 279 } 280 281 .play_bar { 282 position: absolute; 283 left: 200px; 284 top: -10px; 285 z-index: 10; 286 transform: rotate(-25deg); 287 transform-origin: 12px 12px; 288 transition: 1s; 289 } 290 /* 播放杆 转回去 */ 291 .player_con.playing .play_bar { 292 transform: rotate(0); 293 } 294 /* 搜索历史列表 */ 295 .search_history { 296 position: absolute; 297 width: 296px; 298 overflow: hidden; 299 background-color: rgba(255, 255, 255, 0.3); 300 list-style: none; 301 right: 23px; 302 top: 50px; 303 box-sizing: border-box; 304 padding: 10px 20px; 305 border-radius: 17px; 306 } 307 .search_history li { 308 line-height: 24px; 309 font-size: 12px; 310 cursor: pointer; 311 } 312 .switch_btn { 313 position: absolute; 314 right: 0; 315 top: 0; 316 cursor: pointer; 317 } 318 .right_line { 319 position: absolute; 320 left: 0; 321 top: 0; 322 } 323 .video_con video { 324 position: fixed; 325 width: 800px; 326 height: 546px; 327 left: 50%; 328 top: 50%; 329 margin-top: -273px; 330 transform: translateX(-50%); 331 z-index: 990; 332 } 333 .video_con .mask { 334 position: fixed; 335 width: 100%; 336 height: 100%; 337 left: 0; 338 top: 0; 339 z-index: 980; 340 background-color: rgba(0, 0, 0, 0.8); 341 } 342 .video_con .shutoff { 343 position: fixed; 344 width: 40px; 345 height: 40px; 346 background: url("../images/shutoff.png") no-repeat; 347 left: 50%; 348 margin-left: 400px; 349 margin-top: -273px; 350 top: 50%; 351 z-index: 995; 352 }
View Code