html5 同步歌词-VUE获取网易云音乐socket并实现歌词滚动效果

2024-02-10 0 5,347 百度已收录

VUE获取网易云音乐socket并实现歌词滚动效果

最近在修补个人博客,增加了一个播放音乐的模块,所以在这里记录一下播放歌词实时滚动效果的实现,顺便总结一下,加深一下对各个知识点的理解观点。

GitHub地址

演示地址

该功能尚未完全开发。 当前部分可以通过导航栏进入音乐模块,点击下方歌手图片进入。

先给大家看一下治疗效果图。

这里主要有两个组件歌曲信息组件歌曲控制组件。 歌曲控制组件还没有建立。 这里主要记录一下歌曲信息组件的实现。

歌曲信息组件

这部分主要是歌曲列表和当前歌曲信息

1.歌单实现

在此之前,网易云音乐socket的使用请参考网易云音乐API文档

主意:

获取歌曲数据,处理歌曲数据并渲染到视图

(1)实例创建后,即创建的钩子函数期间,我们可以访问data、compute、methods上的技术和数据,然后可以向socket发送请求。

created() {
    //通过getSong()获取对应歌曲信息
    this.getSong(this.$route.query.name); //在这之前,我是通过路由进入的该组件,所以会传递一个name歌手名字作为参数
};

(2)接下来编译getSong()html5 同步歌词,通过axios获取数据。 我们可以先复制下来看看。

    getSong(name) {
      let url =
        "https://api.imjad.cn/cloudmusic/?type=search&search_type=1&s=" +
        name +
        "&offset=1&limit=10"; //这里以第一页的十条数据为例
      this.$axios
        .get(url)
        .then(res => console.log(res.data))
        .catch();
    }

(3) 打开控制台。 很明显,我们得到的并不是我们最终想要的结果,所以我们需要从大量的数据中提取出我们想要的信息。

通常一个歌单所需的数据无外乎如下:

我们可以随意点击其中一个来查找。 至于怎么找到……我们就一一搜索吧。 比如上面有一个name属性,很可能就是歌曲的标题。 socket文档中歌手对应的类型是artist,那么我们就去找这个属性。 如果没有的话,很大概率是短语的缩写,于是我们点击了ar属性,找到了我们想要的。

这一步我们也能感受到参数语义在编码过程中的重要性。

(4)最后,找到我们想要的数据后,我们使用formatSongs()来组织它。

    //提取歌曲信息,arr为接口返回的初始数据
    formatSongs(arr) {
      let n = arr.length;
      for (let i = 0; i < n; i++) {
        let obj = {}; //我们将每首歌的信息以对象的方式存储
        obj.id = arr[i].id;
        obj.song = arr[i].name;
        obj.singer = arr[i].ar[0].name;
        obj.dt = this.formatDt(arr[i].dt); //由于返回的歌曲时长单位是ms,我们还要将其转换成00:00的格式
        this.songList.push(obj); //最后将这个歌曲对象存储到组件的songList歌曲列表属性上,最后用个v-for就可以在视图上呈现出来了
      }
    }
    //格式化播放时长
    formatDt(time) {
      let dt = time / 1000;
      let m = parseInt(dt / 60);
      let s = parseInt(dt % 60); //这里用Math.ceil取整会更严谨些
      m >= 10 ? m : (m = "0" + m);
      s >= 10 ? s : (s = "0" + s);
      return m + ":" + s;
    }

歌曲列表的实现比较简单,不包含标签样式。

2. 获取当前播放歌曲的信息

主意:

获取歌曲信息(主要是歌词)并处理歌曲数据(主要处理歌词格式),实现歌词滚动效果

(1)获取歌词信息

直接上传代码

//获取歌词信息,id为歌曲id
    getLyric(id) {
      let url = "https://api.imjad.cn/cloudmusic/?type=lyric&id=" + id; //获取歌词信息要设置type=lyric,详情看接口文档
      this.$axios
        .get(url)
        .then(res => ((this.lyric = []), this.formatLyric(res.data.lrc.lyric))) 
        .catch();//同样的,我们先要在接口返回的数据中提取出我们需要的那部分,并用一个formatLyric方法来对它进行格式化
    }

(2)在对歌词进行低级处理之前,我们先随机播放一首歌曲,看看原来的歌词文本是什么样子的。

它看起来还不错,有一定的图案,甚至还帮我们改了线。

我们需要做的就是将时间和文本部分分开......一切都在掌控之中html5 同步歌词,直到我发现这一点......

好的! 原来还有这些写法。 不同时间重复的歌词可以写在一起。 确实,这样的写法简单多了,但是我们也要处理更多的事情……

好吧,我们直接上代码

(3)处理歌词文本

//传入初始歌词文本text
formatLyric(text) {
      let arr = text.split("n"); //原歌词文本已经换好行了方便很多,我们直接通过换行符“n”进行切割
      let row = arr.length; //获取歌词行数
      for (let i = 0; i < row; i++) {
        let temp_row = arr[i]; //现在每一行格式大概就是这样"[00:04.302][02:10.00]hello world";
        let temp_arr = temp_row.split("]");//我们可以通过“]”对时间和文本进行分离
        let text = temp_arr.pop(); //把歌词文本从数组中剔除出来,获取到歌词文本了!
        //再对剩下的歌词时间进行处理
        temp_arr.forEach(element => {
          let obj = {};
          let time_arr = element.substr(1, element.length - 1).split(":");//先把多余的“[”去掉,再分离出分、秒
          let s = parseInt(time_arr[0]) * 60 + Math.ceil(time_arr[1]); //把时间转换成与currentTime相同的类型,方便待会实现滚动效果
          obj.time = s;
          obj.text = text;
          this.lyric.push(obj); //每一行歌词对象存到组件的lyric歌词属性里
        });
      }
      this.lyric.sort(this.sortRule); //由于不同时间的相同歌词我们给排到一起了,所以这里要以时间顺序重新排列一下
      this.$store.commit("setLyric", this.lyric); //把歌词提交到store里,为了重新进入该组件时还能再次渲染
    },
    sortRule(a, b) { //设置一下排序规则
      return a.time - b.time;
    }

(4)低格式完成后,我们还通过v-for将歌词渲染到视图中。 接下来我们要做的就是让歌词随着播放的进行而向上滚动。

主要思路如下:

我们先来看看歌词元素的放置。 主要分为三个部分:蓝色框是放置歌词的位置。 我们设置一个位置:相对; 不用担心。 白色的盒子就是我们需要连接的部分。 通过Setabsolute绝对定位。 当歌曲进度更新时,我们可以改变它的top值来达到向下滚动的效果。 不过,只要我们加上overflow:hidden; 到绿色框,我们可以隐藏多余的部分,最终得到之前的效果。 图片功效。

我们使用watch来监听歌曲进度的变化,也就是当前的播放时间。

watch: {
    lyricCurrent() {
      this.lyric.forEach((element, index) => {
        if (this.lyricCurrent == element.time) {
          this.lyricMove.top = -index * 2.5 + 6 + "rem";
          this.currentRow = index; //通过比较我们歌词属性里的时间与当前播放时间,来定位到该歌词
        }
      });
    }
  }

<el-row type="flex" justify="center" class="lyric-contain">
          <el-col :span="23" class="song-lyric" :style="lyricMove">
          
            <el-row
              v-for="(item,index) in lyric"
              :key="index"
              :style="{'font-size': (index==currentRow ? '1.3rem':'.9rem')}"
              class="lyric-row"
            >{{item.text}}</el-row>
          </el-col>
        </el-row>

写在最后:

它还涉及到多个组件,以及状态管理等,所以我没有贴出全部代码。 更多的是提供一个实现思路。 有些地方可能表达不准确,欢迎大家批评指正。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 html5 html5 同步歌词-VUE获取网易云音乐socket并实现歌词滚动效果 https://www.wkzy.net/game/199850.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务