Vue实现仿音乐播放器11-实现访问百度音乐API实现播放音乐功能

场景

从今日推荐页面点击某首歌曲会将这首歌曲的songid通过路由传递到播放界面,

播放界面调用百度音乐接口实现数据的获取以及音乐的播放。

效果

实现

配置路由

首先在pages目录下新建musicplay.vue作为音乐播放的页面,

然后在router下的index.js中中配置路由。

  routes: [
    {
      path:"/musicplay",
      name:"MusicPlay",
      component:MusicPlay
    },

来到今日推荐页面,配置页面跳转

跳转到音乐播放组件并将当前音乐的songid通过路由参数传递过去。

  <div class="scroller">
                <router-link tag="div" :to="{name:'MusicPlay',params:{songid:item.song_id}}" class="card url" v-for="(item,index) in todayRecommend" :key="index">
                    <div class="album">
                        <img :src="item.pic_big" :alt="item.title">
                        <div class="name">{{ item.title }}</div>
                    </div>
                </router-link>
 </div>

同理将其他页面,要实现播放的页面组件也配置跳转到音乐播放组件,并将要播放的音乐组件的songid传递过去。

实现音乐播放界面

百度音乐API播放说明:

例:method=baidu.ting.song.play&songid=877578

例:method=baidu.ting.song.playAAC&songid=877578

参数:songid = 877578 //歌曲id

注:关于使用file_link不能播放的问题,是因为百度使用Http中的Referer头字段来防止盗链,在HTML文件中

加上 <meta name=”referrer” content=”never”>这一句让发送出去的Http包都不含Referer字段

来到musicplay.vue

CSS样式

<style scoped>


.header{
 padding:15px;
}

.music-info{
 flex: 1;
 font-size: 20px;
}

.title{
 display: flex;
 text-align: center;
}

.left{
 font-size: 30px;
}

.ca{
  color: red;
}

.right{
 font-size: 30px;
}

.song-info{
 padding: 15px;
}

.song-info-img{
 text-align: center;
}

.song-info-img img{
 width: 50%;
 border-radius: 5px;
 box-shadow: 0 0 10px 0 rgba(50,50,50,.31);
}

.song-lrc{
 margin-top: 10px;
  min-height: 50px;
}

.iconbox{
 display: flex;
 margin-top: 30px;
}

.iconbox .box{
 flex: 1;
}

.song{
 width: 100%;
 text-align: center;
}

.song audio{
 width: 80%;
}

.active{
  color: #222;
}

.author{
  font-size: 12px;
  color: #999;
}

</style>

页面布局

<template lang="html">
  <div class="play">
    <div class="header">
     <div class="title">
       <router-link to="/">
         <i class="iconfont icon-shouye left"></i>
       </router-link>
       <div class="music-info">
         <p>{{ currentUrl.songinfo.title }}</p>
         <p class="author">{{ currentUrl.songinfo.author }}</p>
       </div>
       <router-link to="/search"><i class="iconfont icon-sousuo right"></i></router-link>
     </div>
   </div>

   <div class="song-info">
   <div class="song-info-img">
        <img :src="currentUrl.songinfo.pic_big">
        <LRC :durationTime="durationTime" :currentTime="currentTime" :songid="this.$route.params.songid"/>
   </div>
   <div class="iconbox">
    <i class="iconfont icon-shoucang2 left"></i>
    <i class="box"></i>
    <i class="iconfont icon-xiazai right"></i>
   </div>
  </div>
    <div class="song">
      <audio ref="player" :src="currentUrl.bitrate.show_link" controls autoplay></audio>
  </div>

  </div>
</template>

实现歌词滚动功能

在components目录下新建LRC.vue

<template lang="html">
  <div class="lrcContainer">
    <div class="lrc" ref="lrc">
      {{ getAllKey }}
      <p
        class="lrc-p"
        :class="{active:parseInt(currentTime) >= keyArr[index] && parseInt(currentTime) < keyArr[index+1]}"
        v-for="(item,key,index) in lrcData"
        :key="index">
        {{ item }}{{ srcollLrc(key,index) }}
      </p>
    </div>
  </div>
</template>

<script>
export default {
  name:"lrc",
  data(){
    return{
      lrc:{},
      lrcData:{},
      keyArr:[]
    }
  },
  props:{
    songid:{
      type:[String,Number],
      default:""
    },
    currentTime:{
      type:[String,Number],
      default:0
    },
    durationTime:{
      type:[String,Number],
      default:0
    }
  },
  mounted(){
    const LRCUrl = this.HOST+"/v1/restserver/ting?method=baidu.ting.song.lry&songid="+this.songid;
    this.$axios.get(LRCUrl)
     .then(res => {
       this.lrc = res.data
       // 数据格式处理
       var lyrics = res.data.lrcContent.split("\n");
        var lrcObj = {};
        for(var i = 0 ;i<lyrics.length;i++){
          var lyric = decodeURIComponent(lyrics[i]);
          var timeReg = /\[\d*:\d*((\.|\:)\d*)*\]/g;
          var timeRegExpArr = lyric.match(timeReg);
          if(!timeRegExpArr)continue;
          var clause = lyric.replace(timeReg,'');
             for(var k = 0,h = timeRegExpArr.length;k < h;k++) {
                 var t = timeRegExpArr[k];
                 var min = Number(String(t.match(/\[\d*/i)).slice(1)),
                     sec = Number(String(t.match(/\:\d*/i)).slice(1));
                 var time = min * 60 + sec;
                 lrcObj[time] = clause;
             }
           }
           this.lrcData = lrcObj;
     })
     .catch(error => {
       console.log(error);
     })
  },
  computed:{
    getAllKey(){
      for(var i in this.lrcData){
        this.keyArr.push(i);
      }
    }
  },
  methods:{
    srcollLrc(key,index){
      const lrcDiv = this.$refs.lrc
       if(key < this.currentTime && key > this.currentTime - (this.keyArr[index+1] - this.keyArr[index])){
           lrcDiv.style.top = -((index-2)*30)+"px"
       }
    }
  }
}
</script>

<style scoped>

.lrcContainer{
  width: 100%;
  height: 150px;
  overflow: hidden;
  position: relative;
}

.lrc{
 width: 100%;
  position: absolute;
  top: 0;
}
.active{
  color: red !important;
}
.lrc-p{
  height: 30px;
 line-height: 30px;
}

.up30{
 margin-top: -30px;
}


</style>


在musicplay.vue显示歌词滚动

<div class="song-info-img">
        <img :src="currentUrl.songinfo.pic_big">
        <LRC :durationTime="durationTime" :currentTime="currentTime" :songid="this.$route.params.songid"/>
   </div>

在musicplay.vue异步操作

// 异步操作
const LRC = Vue.component("lrc",(resolve)=>require(["../components/LRC"],resolve))

添加监听

  methods:{
    addEventListeners(){
      this.$refs.player.addEventListener('timeupdate', this._currentTime),
      this.$refs.player.addEventListener('canplay', this._durationTime)
     },
     removeEventListeners: function () {
       this.$refs.player.removeEventListener('timeupdate', this._currentTime)
       this.$refs.player.removeEventListener('canplay', this._durationTime)
     },
    _currentTime(){
      this.currentTime = this.$refs.player.currentTime
      // currentTime是audio标签提供的获取当前播放时间的方法
    },
   _durationTime(){
    this.durationTime = this.$refs.player.duration
    // duration是audio标签提供的获得歌曲播放整体时间的方法
    }
  }

实现下载功能

百度音乐API下载说明:

例:method=baidu.ting.song.downWeb&songid=877578&bit=24&_t=1393123213

参数: songid = 877578//歌曲id

bit = 24, 64, 128, 192, 256, 320 ,flac//码率

_t = 1430215999,, //时间戳

我们在请求百度音乐的API后输出返回的数据可以看到

歌曲的链接为:

返回数据下的bitrate下的show_link

所以我们几将audio的src属性设为

  <div class="song">
      <audio ref="player" :src="currentUrl.bitrate.show_link" controls autoplay></audio>
  </div>

所以我们点击播放组件的右边的三个点,选择下载,就可以实现下载了。

完整musicplay.vue代码

<template lang="html">
  <div class="play">
    <div class="header">
     <div class="title">
       <router-link to="/">
         <i class="iconfont icon-shouye left"></i>
       </router-link>
       <div class="music-info">
         <p>{{ currentUrl.songinfo.title }}</p>
         <p class="author">{{ currentUrl.songinfo.author }}</p>
       </div>
       <router-link to="/search"><i class="iconfont icon-sousuo right"></i></router-link>
     </div>
   </div>

   <div class="song-info">
   <div class="song-info-img">
        <img :src="currentUrl.songinfo.pic_big">
        <LRC :durationTime="durationTime" :currentTime="currentTime" :songid="this.$route.params.songid"/>
   </div>
   <div class="iconbox">
    <i class="iconfont icon-shoucang2 left"></i>
    <i class="box"></i>
    <i class="iconfont icon-xiazai right"></i>
   </div>
  </div>
    <div class="song">
      <audio ref="player" :src="currentUrl.bitrate.show_link" controls autoplay></audio>
  </div>

  </div>
</template>

<script>

import Vue from "vue"
import "../assets/font/iconfont.css"
// import LRC from "../components/LRC"
// 异步操作
const LRC = Vue.component("lrc",(resolve)=>require(["../components/LRC"],resolve))

export default {
  name:"musicplay",
  data(){
    return{
      currentUrl:{
        songinfo:{
          title:"",
          author:""
        },
        bitrate:{
          show_link:""
        }
      },
      currentTime:0,
      durationTime:0
    }
  },
  components:{
    LRC
  },
  mounted(){
    const playUrl = this.HOST+"/v1/restserver/ting?method=baidu.ting.song.play&songid=" + this.$route.params.songid;
    this.$axios.get(playUrl)
      .then(res => {
        this.currentUrl = res.data;
      })
      .catch(error => {
        console.log(error);
      })
    this.addEventListeners();
  },
  beforeDestroyed(){
    this.removeEventListeners();
  },
  methods:{
    addEventListeners(){
      this.$refs.player.addEventListener('timeupdate', this._currentTime),
      this.$refs.player.addEventListener('canplay', this._durationTime)
     },
     removeEventListeners: function () {
       this.$refs.player.removeEventListener('timeupdate', this._currentTime)
       this.$refs.player.removeEventListener('canplay', this._durationTime)
     },
    _currentTime(){
      this.currentTime = this.$refs.player.currentTime
      // currentTime是audio标签提供的获取当前播放时间的方法
    },
   _durationTime(){
    this.durationTime = this.$refs.player.duration
    // duration是audio标签提供的获得歌曲播放整体时间的方法
    }
  }

}
</script>

<style scoped>


.header{
 padding:15px;
}

.music-info{
 flex: 1;
 font-size: 20px;
}

.title{
 display: flex;
 text-align: center;
}

.left{
 font-size: 30px;
}

.ca{
  color: red;
}

.right{
 font-size: 30px;
}

.song-info{
 padding: 15px;
}

.song-info-img{
 text-align: center;
}

.song-info-img img{
 width: 50%;
 border-radius: 5px;
 box-shadow: 0 0 10px 0 rgba(50,50,50,.31);
}

.song-lrc{
 margin-top: 10px;
  min-height: 50px;
}

.iconbox{
 display: flex;
 margin-top: 30px;
}

.iconbox .box{
 flex: 1;
}

.song{
 width: 100%;
 text-align: center;
}

.song audio{
 width: 80%;
}

.active{
  color: #222;
}

.author{
  font-size: 12px;
  color: #999;
}

</style>

解决Referrer Policy: no-referrer-when-downgrade

场景

原因

百度使用Http中的Referer头字段来防止盗链,在HTML文件中加上 <meta name=”referrer” content=”never”>这一句让发送出去的Http包都不含Referer字段就行了

解决

找到index.html

加入

<meta name="referrer" content="never">

注意双引号是英文状态

此部分代码对应分阶段代码中阶段八

分阶段代码下载位置:

https://download.csdn.net/download/badao_liumang_qizhi/10846557

猜你喜欢

转载自blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/84995491
今日推荐