📖手撸Vue 实现音乐播放功能
前言
因为之前一直想弄一个音乐播放的站点,但不知道用什么框架去写比较好,恰好看见一个可以用的网易云音乐API打算用来测试下
所以样式我就没怎么太注意去写了,功能也是简单实用的几个,可以用来挂着听歌(虽然没有软件好用)
代码量比较多,嫌麻烦的可以直接复制源码,源码我也写了很多译释,直接复制下来放到自己页面应该可以运行
框架:Vue-cli,jQuery,bootstrap,
音乐播放站点 》》
源码
废话不多说,直接上源码
<template>
<div id="music">
<div class="b_img"><img src="../../assets/image/musicimg.jpg"></div>
<div id="back_img"><div style="height:37px;background-color:#fff;z-index: 1;position: relative;"></div><img v-bind:src="muimg"></div>
<div id="music_bo">
<div class="title">
<p class="title_h1">歌名:{{gename}}</p>
<p class="title_info">歌手:<b v-for="name in usname">{{name}} </b></p>
</div>
<div class="in_left"><button @click="musicshang()" class="no_button"><i class="glyphicon glyphicon-step-backward" title="上一首"></i></button></div>
<div class="in_img"><img v-bind:src="muimg" class="max_img">
<button class="zan_an" @click="bo()"><i class="glyphicon glyphicon-play" title="暂停"></i></button></div>
<div class="in_right">
<button @click="musicxia()" class="no_button"><i class="glyphicon glyphicon-step-forward" title="下一首"></i></button>
<button class="no_button list_ge" @click='gelist()'><i class="glyphicon glyphicon-th-large" title="歌单列表"></i></button>
</div>
<audio controls v-bind:src="bofangmu" id="xqt"></audio>
</div>
<button @click="shou()" class="ce_bun"><i class="glyphicon glyphicon-chevron-left"></i></button>
<div id="ge_dan">
<div class="list-group">
<a href="javascript:;" class="list-group-item active">
<h4 class="list-group-item-heading">歌单</h4>
</a>
<ul class="listgun_ul">
<a href="javascript:;" class="list-group-item" v-for="list in gedan" @click='listfun(list.id)'>
<h4 class="list-group-item-heading">{{list.name}}</h4>
</a>
</ul>
</div>
</div>
</div>
</template>
<script>
const axios = require('axios');
export default{
name:"music",
data(){
return {
music:[1364400123,480426313,1309896289,1344897943,1360740361,1426649237,1404906595,480353,2059056,29482234,1400256289,1406642934,1386259535,1409329655,1335580481,527957820,468176711,574566207,1316460171,536099160,534542079,1313354324,27890306,1328146041,31445554,552594869,471565190,480580003,425828896,29004400,514761281,536502758,1330348068,25706282,32083133,1460474276,4879345,524543708,427606780,1410840088,760037,492145159,461544312,507585220,411314681,465920383,21253966,28248872,1491585,1321385655,863046037,515601126,30212890,422132115,533465371,440208476,410802679,1313107065,438981337,465675773,5162502,17753288,29769734,21038748,409931224,534542015,18161816,2918954,463352636,26565006,19081573,28830412,26429346,466122460,21253958,444269135,440101136,418602088,19542383,455653437,27946894,468882985,19711382,29009655,466794339,32574252,3570196,1345018,461347998,36990266,28681438],
bofangmu:'',//歌曲url
muimg:'',//歌曲封面图片
gename:'',//歌曲名
usname:[],//歌手
gedan:[],//歌单
arynum:0,//获取上方歌曲ID
shou_s:true//点击展开与隐藏
};
},
mounted(){
var that=this;
this.axiosmu(this.music[this.arynum]);
let player = document.getElementById('xqt');
player.ontimeupdate = function () {
if(player.currentTime == player.duration){//判断当前歌曲是否播放完
that.musicxia();//执行下一首
}
}
},
methods:{
axiosmu(numb){//获取歌曲信息
var that =this;//解决this:null问题
axios.all([this.getUserAccount(numb), this.getUserPermissions(numb)])//并发执行函数
.then(axios.spread(function (acct, perms) {
that.bofangmu = acct.data.data[0].url;//获取歌的链接
that.muimg =perms.data.songs[0].al.picUrl;//获取图片链接
that.gename =perms.data.songs[0].al.name;//获取歌名
for(let i=0;i<perms.data.songs[0].ar.length;i++){//循环获取歌手
that.usname[i]=perms.data.songs[0].ar[i].name;
}
}));
},
getUserAccount(e) {return axios.get('https://api.imjad.cn/cloudmusic/?id='+e);},//获取音乐链接
getUserPermissions(e) {return axios.get('https://api.imjad.cn/cloudmusic/?type=detail&id='+e);},//获取图像
musicxia(){//下一首
let ap = this.music[this.arynum+=1];
if(this.arynum>=this.music.length){
this.arynum=0;
this.axiosmu(ap);//发送下一首ID
}else{
let that=this;
this.axiosmu(ap);
setTimeout(function () {//利用定时器功能下一首时,自动播放
that.xia_bo();
},1000)
}
},
musicshang(){//上一首
let that=this;
let ap = this.music[this.arynum-=1];
if (this.arynum<0) {
this.arynum=this.music.length;
this.axiosmu(ap);//发送上一首ID
}else{
this.axiosmu(ap);
setTimeout(function () {//利用定时器功能下一首时,自动播放
that.xia_bo();
},1000)
}
},
bo(){//点击播放按钮
let player = document.getElementById('xqt');
if(player.paused){
player.play();
$(".glyphicon-play").addClass("glyphicon-pause");
$(".in_img").addClass("dong");
$(".zan_an").removeClass("zan_an_au");
}else{
player.pause();
$(".glyphicon-play").removeClass("glyphicon-pause");
$(".in_img").removeClass("dong");
$(".zan_an").addClass("zan_an_au");
}
},
xia_bo(){//点击下一首与上一首开始播放
let player = document.getElementById('xqt');
player.play();
$(".glyphicon-play").addClass("glyphicon-pause");
$(".in_img").addClass("dong");
$(".zan_an").removeClass("zan_an_au");
},
shou(){//展开与隐藏歌曲控件
$('#music_bo').animate({width:'toggle'},350);
$('#back_img').animate({width:'toggle'},350);
if(this.shou_s){
$('.ce_bun').animate({left:'0'},350);
$('.ce_bun i').css({"transform":"rotate(180deg)","color":"#bd3a3a"});
this.shou_s =false;
}else{
$('.ce_bun').animate({left:'310px'},350);
$('.ce_bun i').css({"transform":"rotate(0deg)","color":"#fff"});
this.shou_s =true;
}
},
gelist(e){//歌单列表
var that =this;//解决this:null问题
if (this.gedan<=1) {
for(let i=0;i<this.music.length;i++){
axios
.get('https://api.imjad.cn/cloudmusic/?type=detail&id='+this.music[i])
.then(response => (//在数组的底部增加新元素
that.gedan.push({id:response.data.songs[0].id,name:response.data.songs[0].al.name})
))
}
$("#ge_dan").slideToggle("slow");
}else{
$("#ge_dan").slideToggle("slow");
}
$(".list_ge").toggleClass("red");
},
listfun(id){//点击列表的播放时
let that=this;
this.axiosmu(id);
}
}
}
</script>
<style scoped>
.red{color:#bd3a3a!important;border:2px solid #bd3a3a!important;}
body{
background-color: #E5F3FE;
}
.max_img{
width: 100px;
height: 100px;
overflow: hidden;
border-radius: 88px;
border: 2px solid #fff;
}
#back_img{
position: absolute;
top: 400px;
z-index: 1;
width: 310px;
filter: blur(20px);
height: 200px;
border-radius: 20px;
overflow: hidden;
}
#back_img img{width: 108%;height: 100%;margin-top: -13%;}
#music{margin-top: -20px;}
.b_img{height: calc(100vh);width:100%;overflow: hidden;}
.b_img img{width:100%}
#music_bo{
padding: 10px;
position: absolute;
top: 400px;
z-index: 2;
width: 310px;
height: 181px;
overflow: hidden;
border-top-right-radius: 20px;
border-bottom-right-radius: 20px;
}
.title{background-color:#fff;}
.title_h1,.title_info{color:#000;
width:50%;
float:left;
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;}
#xqt{
width: 158%;
height: 26px;
margin-left: -17%;
border-radius: 15px;
overflow: hidden;
background-color: #fff;
margin-top: 5%;
}
.in_left{width: 32%;float: left;}
.in_img{width: 35%;float: left;overflow: hidden;max-height: 100px;}
.in_right{width: 32%;float: left;}
.dong{animation:myfirst 5s infinite linear;}
@keyframes myfirst
{
0% {transform:rotate(0deg);}
10% {transform:rotate(36deg);}
20% {transform:rotate(72deg);}
30% {transform:rotate(108deg);}
40% {transform:rotate(144deg);}
50% {transform:rotate(180deg);}
60% {transform:rotate(216deg);}
70% {transform:rotate(252deg);}
80% {transform:rotate(288deg);}
90% {transform:rotate(324deg);}
100% {transform:rotate(360deg);}
}
.zan_an_au{color:#bd3a3a!important;border:2px solid #bd3a3a!important;opacity: 1!important;}
.in_img:hover >.zan_an{opacity: 1;transition: 1s;}
.zan_an{
transition: 1s;
opacity: 0;
background: none;
border: 2px solid #fff;
position: relative;
top: -76px;
width: 50px;
height: 50px;
border-radius: 33px;
color:#fff;
}
.no_button{
background: none;
border: 2px solid #fff;
font-size: 16px;
border-radius: 15px;
color: #fff;
margin:10%;
width: 28%;
height: 28px;
}
.zan_an i{
font-size:22px;
}
.ce_bun{
position: absolute;
top: 421px;
left: 310px;
z-index: 3;
height: 50px;
width: 29px;
font-size: 19px;
background: #5347478a;
border: none;
color: #fff;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
#ge_dan{
display:none;
position: absolute;
top: 54px;
right: 0px;
width: 20%;
}
.listgun_ul{
overflow: auto;
height: 600px;
width:100%;
padding: 0;
}
.listgun_ul a h4{
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
}
.list_ge{
text-align: right;
}
</style>
JS 分块解释
data(){
return {
music:[1364400123,480426313,1309896289,1344897943,1360740361,1426649237,1404906595,480353,2059056,29482234,1400256289,1406642934,1386259535,1409329655,1335580481,527957820,468176711,574566207,1316460171,536099160,534542079,1313354324,27890306,1328146041,31445554,552594869,471565190,480580003,425828896,29004400,514761281,536502758,1330348068,25706282,32083133,1460474276,4879345,524543708,427606780,1410840088,760037,492145159,461544312,507585220,411314681,465920383,21253966,28248872,1491585,1321385655,863046037,515601126,30212890,422132115,533465371,440208476,410802679,1313107065,438981337,465675773,5162502,17753288,29769734,21038748,409931224,534542015,18161816,2918954,463352636,26565006,19081573,28830412,26429346,466122460,21253958,444269135,440101136,418602088,19542383,455653437,27946894,468882985,19711382,29009655,466794339,32574252,3570196,1345018,461347998,36990266,28681438],
bofangmu:'',//歌曲url
muimg:'',//歌曲封面图片
gename:'',//歌曲名
usname:[],//歌手
gedan:[],//歌单
arynum:0,//获取上方歌曲ID
shou_s:true//点击展开与隐藏
};
},
DATA
music 存放歌曲ID
这里存放的都是网易云歌曲的ID,鼠标移到到网页版的网易云可以看见ID
mounted(){
var that=this;
this.axiosmu(this.music[this.arynum]);
let player = document.getElementById('xqt');
player.ontimeupdate = function () {
if(player.currentTime == player.duration){//判断当前歌曲是否播放完
that.musicxia();//执行下一首
}
}
},
mounted 生命周期函数
主要作用还是获取需要播放第一首歌的信息
player.ontimeupdate 用来判断当前页面歌曲死否播放完,自动播放下一首
axiosmu(numb){//获取歌曲信息
var that =this;//解决this:null问题
axios.all([this.getUserAccount(numb), this.getUserPermissions(numb)])//并发执行函数
.then(axios.spread(function (acct, perms) {
that.bofangmu = acct.data.data[0].url;//获取歌的链接
that.muimg =perms.data.songs[0].al.picUrl;//获取图片链接
that.gename =perms.data.songs[0].al.name;//获取歌名
for(let i=0;i<perms.data.songs[0].ar.length;i++){//循环获取歌手
that.usname[i]=perms.data.songs[0].ar[i].name;
}
}));
}
由于歌曲信息不是放在同一个API中所以需要同时获取多个API接口,通过 axios.all的 并发功能获取
演唱歌手也不是只有一位,所以循环获得
getUserAccount(e) {return axios.get('https://api.imjad.cn/cloudmusic/?id='+e);},//获取音乐链接
getUserPermissions(e) {return axios.get('https://api.imjad.cn/cloudmusic/?type=detail&id='+e);},//获取图像
实际获取API信息的是这俩函数
musicxia(){//下一首
let ap = this.music[this.arynum+=1];
if(this.arynum>=this.music.length){
this.arynum=0;
this.axiosmu(ap);//发送下一首ID
}else{
let that=this;
this.axiosmu(ap);
setTimeout(function () {//利用定时器功能下一首时,自动播放
that.xia_bo();
,1000)
}
},
musicshang(){//上一首
let that=this;
let ap = this.music[this.arynum-=1];
if (this.arynum<0) {
this.arynum=this.music.length;
this.axiosmu(ap);//发送上一首ID
}else{
this.axiosmu(ap);
setTimeout(function () {//利用定时器功能下一首时,自动播放
that.xia_bo();
},1000)
}
},
上一首,获取歌曲ID列表的总长度来判定上一首歌的ID,下一首的功能也是如此
bo(){//点击播放按钮
let player = document.getElementById('xqt');
if(player.paused){
player.play();
$(".glyphicon-play").addClass("glyphicon-pause");
$(".in_img").addClass("dong");
$(".zan_an").removeClass("zan_an_au");
}else{
player.pause();
$(".glyphicon-play").removeClass("glyphicon-pause");
$(".in_img").removeClass("dong");
$(".zan_an").addClass("zan_an_au");
}
},
xia_bo(){//点击下一首与上一首开始播放
let player = document.getElementById('xqt');
player.play();
$(".glyphicon-play").addClass("glyphicon-pause");
$(".in_img").addClass("dong");
$(".zan_an").removeClass("zan_an_au");
},
bo() 是歌曲图片上面那个播放暂停按钮
xia_bo()是点击下一首与上一首时判定的音乐播放
shou(){//展开与隐藏歌曲控件
$('#music_bo').animate({width:'toggle'},350);
$('#back_img').animate({width:'toggle'},350);
if(this.shou_s){
$('.ce_bun').animate({left:'0'},350);
$('.ce_bun i').css({"transform":"rotate(180deg)","color":"#bd3a3a"});
this.shou_s =false;
}else{
$('.ce_bun').animate({left:'310px'},350);
$('.ce_bun i').css({"transform":"rotate(0deg)","color":"#fff"});
this.shou_s =true;
}
},
gelist(e){//歌单列表
var that =this;//解决this:null问题
if (this.gedan<=1) {
for(let i=0;i<this.music.length;i++){
axios
.get('https://api.imjad.cn/cloudmusic/?type=detail&id='+this.music[i])
.then(response => (//在数组的底部增加新元素
that.gedan.push({id:response.data.songs[0].id,name:response.data.songs[0].al.name})
))
}
$("#ge_dan").slideToggle("slow");
}else{
$("#ge_dan").slideToggle("slow");
}
$(".list_ge").toggleClass("red");
},
listfun(id){//点击列表的播放时
this.axiosmu(id);
}
shou()展示与隐藏音乐播放控件的函数
gelist()中使用.push将获取到的歌曲数据存放到对应的内容中!
listfun()对展示出的歌曲列表点击进行切换歌曲
总结(重点记录)
1:利用 player.paused 可知道当前音乐是否在播放
let player = document.getElementById(‘xqt’);
if(player.paused){
暂停中
}else{
播放中
}
2:音乐播放
player.play();
3:音乐暂停
player.pause();
4:为某元素增加class
$(“.glyphicon-play”).addClass(“glyphicon-pause”);
5:为某元素移除class
$(“.zan_an”).removeClass(“zan_an_au”);
6:利用只执行一次的延迟定时器达到下一首播放功能
setTimeout(function () {that.xia_bo();},1000)
7:axios 通过API获取歌曲信息并整合
axios.all([this.getUserAccount(numb), this.getUserPermissions(numb)])//并发获取
8:将获取到的数据存放在数组中的对象
that.gedan.push({id:response.data.songs[0].id,name:response.data.songs[0].al.name})


