网易云项目播放组件中的进度条拖动bug(elementUI)

因遇到的bug相同,此处部分参考引用了以下文章:vue+element制作音乐播放器播放进度条bug(鼠标拖拽slider滑块滑动到指定位置无效)_hhhhhhhssss的博客-CSDN博客_vue音乐播放器进度条最开始bug还没解决时的效果图bug解决后的效果图项目场景:想自己做一个基于vue仿网易云音乐的音乐网站,在制作播放器的时候用到了element ui里面的slider组件,制作完成后发现使用change的方法无法达到我需要的效果,上网查询发现没有好的方案,后面自己琢磨后发现解决方案问题描述:在进度条制作完成以后,发现可以通过点击定位到进度条相应的位置,但是在用鼠标拖拽进度条时有时候会失败,达不到那种可以通过点击跳转到指定区域的功能,并且在鼠标滑动时,进度条依旧在变化。template:&https://blog.csdn.net/hhhhhhhssss/article/details/110932934

问题描述:

 slider通过点击可定位到相应的位置(或者特别快速的拖动,快速拖动个人认为slider组件应该是利用了mousedown和mouseup并结合定时器从而实现拖拽效果,当特别快速的拖动时,只要没有达到定时器设定的时间间隔,故和鼠标点击是相同效果),但是在用鼠标拖拽进度条时会失败(超过一定时间),进度条会回弹到之前时间点附近,达不到那种可以滑动转到指定区域的功能。

以下为部分相关源码:

<el-slider
    v-model="percent"
    :format-tooltip="formatTooltip"
    @change="changeProgress"
></el-slider>

<audio
   ref="audio"
   :src="currentSong.url"
   @pause="audioPaused"
   @timeupdate="updateTime"
   @ended="audioEnd"
></audio>

data() {
    return {
      // 进度条当前的百分百(即currentTime/duration)
      percent: 0,
      // 当前播放歌曲的时间点
      currentTime: 0,
      // 是否静音
      isMuted: false,
      // 默认音量
      volume: 0.5,
      // 拖动条默认值
      volumeNum: 50,
      // 歌词界面是否打开
      showLyric: false,
    };
  },

methods: {
    // 监听播放时间改变
    updateTime(e) {
      this.currentTime =
        (e.target.currentTime / this.currentSong.duration) * 100;
    },
    // 改变播放进度
    changeProgress(per) {
      const audio = this.$refs.audio;
      audio.currentTime = (per / 100) * this.currentSong.duration;
    },
}

 问题分析:

根据elementUI文档可知,slider组件的change事件使用鼠标拖曳时,只在松开鼠标后触发。根据源码写法可知:当前时长是随着audio的更新而赋值达到实时更新的,而element的slider的change方法是在鼠标松开后才会触发,这样产生的实际情况则是拖动进度条期间,在鼠标松开之前,audio的timeUpdate事件一直在触发,currentTime其实是实时更新的,再次松开鼠标时,changeProgress方法中的audio.currentTime的值并不是鼠标拖拽到的指定进度 ,而是audio的timeupdate事件中的方法赋值给当前时长的进度值,故此会产生进度条回弹效果。 

解决思路 :

在鼠标按下时把audio的timeupdate事件方法禁止,即暂停记录实时的currentTime,在拖拽后鼠标松开的时候解禁timeupdate事件方法,同时把slider组件change事件得到的时间赋值给data中的currentTime,这样就能保证进度条的点就是当前播放的时间点。所以添加progressState参数判断是否在拖拽状态,以此来达到目的。

部分源码如下:

<el-slider
    v-model="percent"
    :format-tooltip="formatTooltip"
    @change="changeProgress"
    @mousedown.native="progressState = true"
    @mouseup.native="progressState = false"
></el-slider>

<audio
   ref="audio"
   :src="currentSong.url"
   @pause="audioPaused"
   @timeupdate="updateTime"
   @ended="audioEnd"
></audio>

data() {
  return {
      // 进度条当前的百分百(即currentTime/duration)
      percent: 0,
      // 当前播放歌曲的时间点
      currentTime: 0,
      // 是否静音
      isMuted: false,
      // 默认音量
      volume: 0.5,
      // 拖动条默认值
      volumeNum: 50,
      // 歌词界面是否打开
      showLyric: false,
      // slider是否处于拖动状态 解决鼠标拖拽slider滑块滑动到指定位置无效
      progressState: false,
  }
}

methods: {
   // 监听播放时间改变
    updateTime(e) {
      if (!this.progressState) {
        this.currentTime = e.target.currentTime;
      this.percent = (e.target.currentTime / this.currentSong.duration) * 100;
      }
    },
    // 拖动进度条改变播放进度时(鼠标拖拽松开时触发)
    changeProgress(per) {
      // this.progressState = true;
      const audio = this.$refs.audio;
      const currentTime = (per / 100) * this.currentSong.duration;
      this.currentTime = currentTime;
      this.percent = per;
      audio.currentTime = currentTime;
    },
}

2022.04.02更新:

上述解决问题还遗留一个bug,因为在el-slider组件中绑定了mouseup事件,当拖拽松开鼠标时,若鼠标离开了slider组件区域(即slider相关的盒子大小区域),会导致mouseup事件触发不了,从而processState一直处于true状态,即认为处于拖动状态,故进度掉会停止向前移动。此处解决思路之一是对mouseup事件进行监听,如下:(不一定必须是window对象,也可是比slider更大盒子的dom元素。或者也可把mouseup事件绑定在更高级的父元素上。暂时解决bug了,但此处解决的还并不完美,日后再完善)

<el-slider
    v-model="percent"
    :format-tooltip="formatTooltip"
    @change="changeProgress"
    @mousedown.native="progressState = true"
    @mouseup.native="changeProgressState"
></el-slider>

<audio
   ref="audio"
   :src="currentSong.url"
   @pause="audioPaused"
   @timeupdate="updateTime"
   @ended="audioEnd"
></audio>

data() {
  return {
      // 进度条当前的百分百(即currentTime/duration)
      percent: 0,
      // 当前播放歌曲的时间点
      currentTime: 0,
      // 是否静音
      isMuted: false,
      // 默认音量
      volume: 0.5,
      // 拖动条默认值
      volumeNum: 50,
      // 歌词界面是否打开
      showLyric: false,
      // slider是否处于拖动状态 解决鼠标拖拽slider滑块滑动到指定位置无效
      progressState: false,
  }
}

methods: {
   // 监听播放时间改变
    updateTime(e) {
      if (!this.progressState) {
        this.currentTime = e.target.currentTime;
      this.percent = (e.target.currentTime / this.currentSong.duration) * 100;
      }
    },
    // 拖动进度条改变播放进度时(鼠标拖拽松开时触发)
    changeProgress(per) {
      // this.progressState = true;
      const audio = this.$refs.audio;
      const currentTime = (per / 100) * this.currentSong.duration;
      this.currentTime = currentTime;
      this.percent = per;
      audio.currentTime = currentTime;
    },
    changeProgressState(e) {
      this.progressState = false;
    },
}

mounted() {
    // 监听slider中的mouseup事件,防止拖拽进度条松开时,鼠标离开特定区域造成事件丢失不生效
    window.addEventListener("mouseup", this.changeProgressState);
},

   
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值