vue项目:歌词随歌曲同步滚动

封装成对象,暴露出去共享使用

1、新建js文件
2、因为需要用到元素运动来实现歌词自上而下滚动的效果,又不想引用jquery增大js的加载,所有在对象内部封装了一个运动函数。
3、主要的函数是添加定时器来实现歌词和歌曲的播放的时间同步,因为歌曲有暂停的功能,所以也添加了清除定时器来实现歌词暂停的功能,此时在对象内部的两个函数中用到了同一个参数定时器,所有需要将定时器定义成对象自身的一个参数来实现参数共享。
4、因为要满足点击某一首歌曲来播放相关的歌词,所以也需要一个函数来重置对象自身的参数。对象内部也需要解析歌词数据的函数,将解析后的歌词数据中的时间点都统一转化成秒,来和audio的当前播放进度(Audio.currentTime)对比,达到歌词滚动同步歌曲播放进度的效果。
5、每次点击播放某一首歌曲都要先重置对象自身的参数,再进行歌词同步滚动。

新建的js代码如下:

export default {
  second2: 0, // 当前歌曲播放到多少毫秒
  gdtimer: '', // 歌词滚动的定时器
  height: 20, // 每一行歌词的高度
  obj: {}, // 解析歌词后的对象
  obj2: {}, // 备份obj
  // 字符串转换成秒
  parse2 (stri) {
    var arr = stri.split(':')
    var num = 0
    num = parseInt(arr[0]) * 60 + parseFloat(arr[1])
    return num
  },
  // 解析歌词
  parse (str) {
    var arr1 = []
    var arr2 = []
    this.obj = {
      time: [],
      content: []
    }
    this.obj2 = {
      time: [],
      content: []
    }
    arr1 = str.split('[')
    arr1.forEach((value, index) => {
      if (index > 0) {
        arr2 = arr2.concat(value.split(']'))
      }
    })
    arr2.forEach((value, index) => {
      if (index % 2 === 0) {
        this.obj.time.push(this.parse2(value))
        this.obj2.time.push(this.parse2(value))
      } else {
        this.obj.content.push(value)
        this.obj2.content.push(value)
      }
    })
  },
  // 将歌词添加到 P 标签中
  addcontent (conp) {
    this.obj.content.forEach((value, index) => {
      conp.innerHTML = conp.innerHTML + value + '
' }) }, // 实现歌词滚动 gundong (conp) { this.gdtimer = setInterval(() => { var myaudio = document.querySelector('#main-audio') // console.log(myaudio.currentTime) this.second2 = myaudio.currentTime // this.second2 = this.second2 + 10 if (this.second2 >= this.obj2.time[0]) { // 删除time数组中已经过的时间 this.obj2.time.shift() console.log(this.second2, this) // 获取 p标签的top值 var top = window.getComputedStyle(conp).top this.startMove(conp, { top: parseInt(top) - this.height }) } if (this.obj2.time.length <= 0) { this.second2 = 0 this.lyticsEnd(conp) // clearInterval(this.gdtimer) } }, 50) }, // 暂停歌词 pause () { if (this.gdtimer !== '') { clearInterval(this.gdtimer) // console.log(this.obj) } }, // 歌曲放完,重置该对象 lyticsEnd (conp) { this.pause() conp.innerHTML = '' conp.style.top = this.height + 'px' // 大坑。单位必须带 this.obj = {} this.obj2 = {} this.second2 = 0 console.log('重置该对象成功', this) }, // 运动函数 startMove (obj, json, fnEnd) { var that = this clearInterval(obj.timer)// 先清除之前的定时器 obj.timer = setInterval(function () { var bStop = true// 假设所有的值都到了 for (var attr in json) { // 遍历json属性 var cur = (attr === 'opacity') ? Math.round(parseFloat(that.getStyle(obj, attr)) * 100) : parseInt(that.getStyle(obj, attr))// 对opacity 特殊处理 var speed = (json[attr] - cur) / 6 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed) // speed 数字转化,防止不能到达目标的bug if (cur !== json[attr]) bStop = false// 如果没有达到目标值,则bStop设为false; if (attr === 'opacity') { obj.style.filter = 'alpha(opacity=' + (cur + speed) + ')' obj.style.opacity = (cur + speed) / 100 } else { obj.style[attr] = cur + speed + 'px' } } if (bStop) { clearInterval(obj.timer) if (fnEnd) fnEnd() // 执行回调函数 } }, 30) }, getStyle (obj, name) { return obj.currentStyle ? obj.currentStyle[name] : window.getComputedStyle(obj, null)[name] // 浏览器兼容性处理,注意getComputedStyle为只读属性 }, getByClass (oParent, sClass) { var aEle = oParent.getElementsByTagName('*') var aResult = [] var re = new RegExp('\\b' + sClass + '\\b', 'i') for (var i = 0; i < aEle.length; i++) { if (re.test(aEle[i].className)) aResult.push(aEle[i]) } return aResult } }

vue文件中如下使用:

		import lyrics from '../footer/lyrics'   
		// js文件路径视情况而定
		var conp = document.querySelector('.con-p')
		// 包裹歌词的元素容器
        lyrics.lyticsEnd(conp) // 重置对象
        lyrics.parse(this.lyrics, conp) // 解析歌词  this.lyrics 代表歌词数据
        lyrics.addcontent(conp) // 向元素容器中添加歌词内容
        lyrics.gundong(conp) // 歌词滚动函数

你可能感兴趣的:(Vue)