通过axios加载网易云音乐API
1.歌曲播放,暂停
2.切换上下首
3.显示歌词(自动滑动)
4.搜索音乐(分页)
5.加载评论
6.列表循环,单曲循环,列表随机
7.拉动进度条歌词自动滑动
更多功能可查看api文档https://autumnfish.cn/
1.element.min.js
2.element.min.css
3.axios.min.js
4.axios.min.js
DOCTYPE HTML>
<html lang="en">
<head>
<title>听音乐title>
<meta charset="utf-8">
<meta name="renderer" content="webkit|ie-comp|ie-stand">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
<link rel="stylesheet" type="text/css" href="css/element.min.css" />
<style>
li{
list-style: none;
}
.playing {
transform: rotate(360deg);
animation: rotation 20s linear infinite;
}
@keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.el-table .success-row {
background: #98eed7 !important;
}
.el-table .active-row {
background: #eef5f4 !important;
}
style>
head>
<body>
<div id="app" style="margin-top: 100px;">
<tips>tips>
<div style="width: 100%;height: 600px;position: relative">
<div style="float: right;width: 40%;height: 600px">
<img v-if="!lyricFlag" @click="changeLyricFlag()" id="img" :src="imageUrl" width="300px" height="300px"
style="border-radius: 50%" :class="{playing:isplaying}">
<div v-if="lyricFlag">
<div v-if="lyric" style="width: 330px;height: 40px;background-color: #eef5f4;" >
<el-button @click="changeLyricFlag()" style="outline: none;margin: 5px;position: relative" size="mini">返回el-button>
<span style="margin-left: 20%">歌词span>
div>
<el-card id="lyric" v-if="lyric" style="width: 330px;height: 300px;overflow: auto;position: relative" class="box-card">
<el-table
:row-class-name="lyricRowClassName"
:data="lyric"
:row-style="{height: '0'}"
:cell-style="{padding: '3px'}"
style="width: 100%;text-align: center">
<el-table-column
prop="n"
label=""
width="260">
<template slot-scope="scope">
<span style="color: #8f9393;" >
{{scope.row[1]}}
span>
template>
el-table-column>
el-table>
el-card>
div>
<br> <br>
<el-radio-group style="border: 1px solid #f1f1f1;padding: 10px" v-model="type">
<el-radio :label="1">列表循环el-radio>
<el-radio :label="2">单曲循环el-radio>
<el-radio :label="3">列表随机el-radio>
el-radio-group>
<br><br>
<el-button-group>
<el-button @click="preSong()" size="medium" style="outline: none;height: 40px" type="default" >上一首el-button>
<el-button style="outline: none;height: 40px" size="medium" type="default" ><marquee align="left" behavior="scroll" width="110px" direction="left" loop="-1" scrollamount="2" scrolldelay="2">{{text}}marquee>el-button>
<el-button @click="lasSong()" size="medium" style="outline: none;height: 40px" type="default">下一首el-button>
el-button-group>
<br> <br>
<audio id="audio" :src="url" controls autoplay @play="play" @pause="pause">audio>
div>
<div style="float: left;width: 30%;margin-left: 15%;height: 600px">
<el-input @keyup.enter.native="search" placeholder="搜索歌名或歌手" v-model="keyword" class="input-with-select">
<el-button @click="search()" slot="append" ><svg t="1649990553012" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2028" width="16" height="16"><path d="M1005.312 914.752l-198.528-198.464A448 448 0 1 0 0 448a448 448 0 0 0 716.288 358.784l198.4 198.4a64 64 0 1 0 90.624-90.432zM448 767.936A320 320 0 1 1 448 128a320 320 0 0 1 0 640z" fill="#262626" p-id="2029">path>svg>el-button>
el-input>
<div id="tab" style="overflow: auto;height: 500px;">
<el-table
v-loading="isShowLoading"
v-loading="loading"
element-loading-text="拼命加载中"
:row-class-name="tableRowClassName"
:data="songList"
style="width: 100%">
<el-table-column
type="index"
label="序号"
width="50">el-table-column>
<el-table-column
prop="name"
label="歌名"
width="180">
<template slot-scope="scope">
<span style="color: #0f9ae0;cursor: pointer" @click="getSing(scope.row.id,scope.$index)" >
{{scope.row.name}}
span>
template>
el-table-column>
<el-table-column
prop="ar[0].name"
label="歌手">
el-table-column>
<el-table-column
label=""
width="100">
<template slot-scope="scope">
<el-button type="text" size="small">
<span>
<svg v-if="scope.row.id!=song.id" @click="getSing(scope.row.id,scope.$index)" t="1650264949142" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1999" width="16" height="16"><path d="M512 0C230.4 0 0 230.4 0 512c0 281.6 230.4 512 512 512 117.76 0 227.84-38.4 320-110.08 10.24-7.68 12.8-23.04 5.12-35.84-7.68-10.24-23.04-12.8-35.84-5.12C719.36 939.52 616.96 972.8 512 972.8 256 972.8 51.2 768 51.2 512 51.2 256 256 51.2 512 51.2 768 51.2 972.8 256 972.8 512c0 87.04-25.6 171.52-69.12 243.2-7.68 12.8-2.56 28.16 7.68 33.28 12.8 7.68 28.16 2.56 33.28-7.68 51.2-79.36 76.8-174.08 76.8-271.36C1024 230.4 793.6 0 512 0z" p-id="2000">path><path d="M714.24 458.24c-17.92-15.36-245.76-222.72-245.76-222.72-10.24-10.24-25.6-7.68-35.84 2.56-5.12 5.12-7.68 12.8-7.68 17.92 0 0 0 0 0 0 0 0 0 499.2 0 512 0 15.36 10.24 25.6 25.6 25.6 5.12 0 12.8-2.56 15.36-7.68 2.56-2.56 217.6-186.88 240.64-207.36 23.04-20.48 33.28-38.4 33.28-64C742.4 491.52 732.16 473.6 714.24 458.24zM680.96 535.04c-7.68 5.12-204.8 176.64-204.8 176.64l0-399.36c0 0 186.88 166.4 202.24 181.76C696.32 512 698.88 519.68 680.96 535.04z" p-id="2001">path>svg>
span>
<span v-if="scope.row.id==song.id">
<svg @click="play()" v-if="!isplaying" t="1650264949142" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1999" width="16" height="16"><path d="M512 0C230.4 0 0 230.4 0 512c0 281.6 230.4 512 512 512 117.76 0 227.84-38.4 320-110.08 10.24-7.68 12.8-23.04 5.12-35.84-7.68-10.24-23.04-12.8-35.84-5.12C719.36 939.52 616.96 972.8 512 972.8 256 972.8 51.2 768 51.2 512 51.2 256 256 51.2 512 51.2 768 51.2 972.8 256 972.8 512c0 87.04-25.6 171.52-69.12 243.2-7.68 12.8-2.56 28.16 7.68 33.28 12.8 7.68 28.16 2.56 33.28-7.68 51.2-79.36 76.8-174.08 76.8-271.36C1024 230.4 793.6 0 512 0z" p-id="2000">path><path d="M714.24 458.24c-17.92-15.36-245.76-222.72-245.76-222.72-10.24-10.24-25.6-7.68-35.84 2.56-5.12 5.12-7.68 12.8-7.68 17.92 0 0 0 0 0 0 0 0 0 499.2 0 512 0 15.36 10.24 25.6 25.6 25.6 5.12 0 12.8-2.56 15.36-7.68 2.56-2.56 217.6-186.88 240.64-207.36 23.04-20.48 33.28-38.4 33.28-64C742.4 491.52 732.16 473.6 714.24 458.24zM680.96 535.04c-7.68 5.12-204.8 176.64-204.8 176.64l0-399.36c0 0 186.88 166.4 202.24 181.76C696.32 512 698.88 519.68 680.96 535.04z" p-id="2001">path>svg>
<svg @click="pause()" v-if="isplaying" t="1650265428253" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3012" width="16" height="16"><path d="M352 768c-17.664 0-32-14.304-32-32L320 288c0-17.664 14.336-32 32-32s32 14.336 32 32l0 448C384 753.696 369.664 768 352 768z" p-id="3013">path><path d="M672 768c-17.696 0-32-14.304-32-32L640 288c0-17.664 14.304-32 32-32s32 14.336 32 32l0 448C704 753.696 689.696 768 672 768z" p-id="3014">path>svg>
span>
el-button>
template>
el-table-column>
el-table>
div>
<div class="block">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage"
:page-size="pageSize"
layout="prev, pager, next, jumper"
:total="total">
el-pagination>
div>
div>
div>
<div v-if="song" style="width: 70%;margin: 0 auto">
<h3><svg t="1650270638169" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2976" width="32" height="32"><path d="M371.2 454.4m-51.2 0a0.8 0.8 0 1 0 102.4 0 0.8 0.8 0 1 0-102.4 0Z" p-id="2977">path><path d="M512 454.4m-51.2 0a0.8 0.8 0 1 0 102.4 0 0.8 0.8 0 1 0-102.4 0Z" p-id="2978">path><path d="M652.8 454.4m-51.2 0a0.8 0.8 0 1 0 102.4 0 0.8 0.8 0 1 0-102.4 0Z" p-id="2979">path><path d="M377.6 896c-6.4 0-6.4 0-12.8 0-12.8-6.4-19.2-19.2-19.2-32l0-128C211.2 684.8 128 569.6 128 448c0-179.2 172.8-320 384-320s384 140.8 384 320c0 172.8-166.4 313.6-371.2 320l-128 121.6C390.4 896 384 896 377.6 896zM512 192C332.8 192 192 307.2 192 448c0 102.4 76.8 192 192 236.8 12.8 6.4 19.2 19.2 19.2 32l0 76.8 83.2-76.8C492.8 704 505.6 704 512 704c179.2 0 320-115.2 320-256S691.2 192 512 192z" p-id="2980">path>svg>评论区h3>
<el-table
:data="reviewList"
style="width: 100%;">
<el-table-column
prop="date"
label=""
height="30px"
width="1000px">
<template slot-scope="scope">
<li>
<img :src="scope.row.user.avatarUrl" style="border-radius: 50%;float: left" width="50px" height="50px">
<p style="float: left;width: 90%;position: relative">
<span style="font-weight: bold">{{scope.row.user.nickname}}:span><span>{{scope.row.content}}span>
<span style="float: right;position: relative">
<span>{{scope.row.timeStr}}
span>span>
p>
li>
template>
el-table-column>
el-table>
<div class="block" style="margin-top: 40px;margin-bottom: 30px;">
<el-pagination
@size-change="commentHandleSizeChange"
@current-change="commentHandleCurrentChange"
:current-page.sync="commentCurrentPage"
:page-size="commentPageSize"
layout="prev, pager, next, jumper"
:total="commentTotal">
el-pagination>
div>
div>
div>
<script src="js/vue.min.js">script>
<script src="js/axios.min.js">script>
<script src="js/element.min.js">script>
<script>
var vm = new Vue({
el: "#app",
data: {
songList: [],
url: "",
imageUrl: "images/music.png",
reviewList: [],
isplaying: false,
hotSearch:[],
keyword:"",
text:"请选择歌曲播放",
song:"",
audio:"",
index:-2,
type: 1,
lyric:"",
lyricFlag:false,
lyricIndex:0,
timer:"",
total:0,
pageSize:10,
currentPage:1,
commentTotal:0,
commentPageSize:10,
commentCurrentPage:1,
isShowLoading:false,
loadingCount:0,
searchKey:""
},
created(){
this.config()
},
mounted(){
this.getHotKeyword()
this.audio =document.querySelector('#audio');
this.audio.addEventListener('ended', this.playEndedHandler, false);
audio.addEventListener('timeupdate', this.timeUpdate, false);
},
destroyed() {
this.audio.removeEventListener('ended',this.playEndedHandler,false);
this.audio.removeEventListener('timeupdate',this.playEndedHandler,false);
clearInterval(this.timer)
},
methods: {
//显示加载中
addLoading() {
this.isShowLoading = true
this.loadingCount++
},
//隐藏加载中
isCloseLoading() {
this.loadingCount--
if (this.loadingCount == 0) {
this.isShowLoading = false
}
},
//axios拦截器
config(){
// 添加请求拦截器
axios.interceptors.request.use(config => {
var u=config.url
//url是搜索才显示加载
if(u.indexOf("search")!=-1){
this.addLoading()
}
return config
}, error => {
this.isShowLoading = false
this.loadingCount = 0
alert('网络异常,请稍后再试')
return Promise.reject(error)
})
// 添加响应拦截器
axios.interceptors.response.use(response => {
//url是搜索才显示加载
var u=response.config.url
if(u.indexOf("search")!=-1){
this.isCloseLoading()
}
return response
}, error => {
this.isShowLoading = false
this.loadingCount = 0
alert('网络异常,请稍后再试')
return Promise.reject(error)
})
},
handleSizeChange(val) {
},
commentHandleSizeChange(val) {
},
//列表分页重新搜索
handleCurrentChange(val) {
this.search();
},
//切换评论
commentHandleCurrentChange(val) {
this.getReviews(this.song.id)
this.backTopComment()
},
//提示正在播发
changeText(index){
this.text="正在播放-"+this.songList[index].name+"-"+this.songList[index].ar[0].name
},
//提示已暂停
changeText2(index){
this.text="已暂停-"+this.songList[index].name+"-"+this.songList[index].ar[0].name
},
//歌词跟住进度条
timeUpdate(){
var data=parseInt(audio.currentTime);
this.lyricIndex=data*10
},
//是否显示歌词
changeLyricFlag(){
if(this.song==""){
return
}
this.lyricFlag=!this.lyricFlag
},
//上一首
preSong(){
this.isplaying=false
var pre=this.index-1
if(pre==-1){
pre=this.songList.length-1
}
if(this.index==-2){
pre=0
}
this.getSing(this.songList[pre].id,pre)
},
//下一首
lasSong(){
this.isplaying=false
var las=this.index+1
if(las==this.songList.length){
las=0
}
if(this.index==-2){
las=0
}
this.getSing(this.songList[las].id,las)
},
//歌曲结束前处理
playEndedHandler(){
//继续播放
if(this.type==2){
this.play()
return
}
//随机播放
if(this.type==3){
var ran=Math.floor(Math.random()*this.songList.length);
this.getSing(this.songList[ran].id,ran)
return
}
//下一首播放
this.isplaying=false
var las=this.index+1
if(las==this.songList.length){
las=0
}
this.getSing(this.songList[las].id,las)
},
//列表对应歌曲样式绑定
tableRowClassName({row, rowIndex}) {
if (row.id == this.song.id) {
this.delay()
return 'success-row';
}
},
//对应歌词样式绑定
lyricRowClassName({row, rowIndex}) {
if (row[0] <= (this.lyricIndex/10)&&row[2]>(this.lyricIndex/10)) {
this.moveLyric()
return 'active-row';
}
return ''
},
//歌曲列表滚动
delay() {
var self = this
var t
clearTimeout(t)
t = setTimeout(function() {
let [parentDoc,childDoc]= [document.querySelector('#tab'),document.querySelector('.success-row')];
parentDoc.scrollTop = childDoc.offsetTop - parentDoc.offsetHeight /3 ; //如果大于div高度使其居中
}, 500)
},
//歌词滚动
moveLyric() {
var self = this
var t
clearTimeout(t)
t = setTimeout(function() {
let [parentDoc,childDoc]= [document.querySelector('#lyric'),document.querySelector('.active-row')];
parentDoc.scrollTop = childDoc.offsetTop - parentDoc.offsetHeight /6 ;
}, 300)
},
//搜索歌曲
search(){
let that = this;
if(this.keyword==""){
return
}
if(this.searchKey!=this.keyword){
this.currentPage=1
}
axios.get("https://autumnfish.cn/cloudsearch?offset="+(this.currentPage-1)*this.pageSize+"&limit="+10+"&keywords=" + this.keyword)
.then(function (response) {
that.songList = response.data.result.songs;
that.total=response.data.result.songCount
that.searchKey=that.keyword
}, function (error) {
console.log(error)
});
},
getHotSongs: function (keyword) {
//回调函数需要使用that来传递this
let that = this;
for (const index in keyword) {
axios.get("https://autumnfish.cn/cloudsearch?limit=1&keywords=" + keyword[index].first)
.then(function (response) {
that.songList.push(response.data.result.songs[0]);
}, function (error) {
console.log(error)
});
}
this.total=10
},
//获取热门搜索关键字
getHotKeyword: function () {
//回调函数需要使用that来传递this
let that = this;
axios.get("https://autumnfish.cn/search/hot")
.then(function (response) {
that.hotSearch = response.data.result.hots;
that.getHotSongs(response.data.result.hots)
}, function (error) {
console.log(error)
});
},
//处理歌词
splitLyric(str){
this.lyric=[]
let lyricArr = str.split('[').slice(1);
//存的数组,第一个值为播放的秒数,第二个值为歌词,第三个值为下一句的播放秒数
let lrcObj = [];
var i=0;
lyricArr.forEach(item => {
let arr = item.split(']');
// 时间换算成秒
let m = parseInt(arr[0].split(':')[0])
let s = parseInt(arr[0].split(':')[1])
arr[0] = m*60 + s;
if (arr[1] != '\n') { // 去除歌词中的换行符
arr[2]=-1
lrcObj.push(arr)
}
})
for(;i<lrcObj.length-1;i++){
lrcObj[i][2]=lrcObj[i+1][0]
}
// 存储数据
this.lyric = lrcObj;
},
//获取歌词
getLyric: function () {
//回调函数需要使用that来传递this
let that = this;
axios.get("https://autumnfish.cn//lyric?id="+this.song.id)
.then(function (response) {
that.splitLyric(response.data.lrc.lyric)
}, function (error) {
console.log(error)
});
},
//获得歌曲的在线url地址
getSing: function (id,index) {
let that = this;
axios.get("https://autumnfish.cn/song/url?id=" + id)
.then(function (response) {
//注意返回的是数据数组,需要data[0]
that.url = response.data.data[0].url;
that.song=response.data.data[0]
that.index=index
that.changeText(index)
that.getLyric()
}, function (error) {
console.log(error);
})
this.getImage(id);
this.getReviews(id);
this.isplaying=true
clearInterval(this.timer)
},
//获取歌曲封面
getImage: function (id) {
let that = this;
axios.get("https://autumnfish.cn/song/detail?ids=" + id)
.then(function (response) {
that.imageUrl = response.data.songs[0].al.picUrl;
}, function (error) {
console.log(error);
})
},
//获取歌曲评论
getReviews: function (id) {
let that = this;
axios.get("https://autumnfish.cn/comment/hot?type=0&&offset="+this.commentCurrentPage*this.commentPageSize+"&id=" + id)
.then(function (response) {
that.reviewList = response.data.hotComments;
that.commentTotal=response.data.total
}, function (error) {
console.log(error);
})
},
//回到评论开始
backTopComment() {
const that = this
let timer = setInterval(() => {
document.documentElement.scrollTop = document.body.scrollTop = 630
clearInterval(timer)
}, 16)
},
//播放
play: function () {
var audio =document.querySelector('#audio');
audio.play();
this.isplaying = true;
this.changeText(this.index)
},
//暂停
pause: function () {
var audio =document.querySelector('#audio');
audio.pause();
this.isplaying = false
this.changeText2(this.index)
},
}
});
script>
body>
html>