vue_music:播放器(四):mini播放器和播放进度条

1.mini播放器开关

《vue_music:播放器(四):mini播放器和播放进度条》

1.1 vuex:播放器控制开关fullScreen

初始化的时候,在vuex中获取fullScreen状态

...mapGetters([
      'fullScreen',
······
    ])

1.2 mini→norman播放器切换

open() {
  this.setFullScreen(true)
}

2.mini播放器播放背景图片播放动画

《vue_music:播放器(四):mini播放器和播放进度条》

3. normal播放器进度条

思路

  1. 接收percent,即播放百分比,从而显示进度
  2. 点击进度条,emit相应的百分比,从而更改当前播放时间percentChange
  3. 拖动小圆圈,emit相应的百分比,从而更改当前播放时间percentChange

所以html页面:

<div class="progress-wrapper">
    //当前播放时间
    <span class="time time-l">{{format(currentTime)}}</span>
    <div class="progress-bar-wrapper">
    //进度条:percent = currentTime(当前播放时间) / currentSong.duration(歌曲总时间)
      <Progress-bar @percentChange="onProgressBarChange" :percent="percent"></Progress-bar>
    </div>
    //歌曲总时间
    <span class="time time-r">{{format(currentSong.duration)}}</span>
</div>

3.1 ProgressBar.vue页面布局

《vue_music:播放器(四):mini播放器和播放进度条》

3.2 props接收 percent

进度条:percent = currentTime(当前播放时间) / currentSong.duration(歌曲总时间)
currentTime(当前播放时间)从audio中获取
《vue_music:播放器(四):mini播放器和播放进度条》
const progressBtnWidth = 16 //小圆的宽度

props: {
    percent: {
      type: Number,
      default: 0
    }
  },
  watch: {
    percent(newPercent) {
      //拖动的时候,percent也在改变,这个时候应该拖动的优先级高于watch,所以加!this.initiated
      if (newPercent && !this.initiated) {
        const barWidth = this.$refs.progressBar.clientWidth - progressBtnWidth
        //相乘得出黄色进度调的距离
        const offsetWidth = newPercent * barWidth
        this._offset(offsetWidth)
      }
    }
  },

//计算:黄色进度条宽度 小圆圈的位置

 _offset(offsetWidth) {
//黄色进度条宽度
      this.$refs.progress.style.width = `${offsetWidth}px`
//小圆圈的位置
      this.$refs.progressBtn.style[transform] = `translate3d(${offsetWidth}px, 0, 0)`
    }

3.3拖动进度条联动

拖动,touch事件
created中定义this.touch = {}

progressTouchStart(e) {
//拖动的时候,percent也在改变,这个时候应该拖动的优先级高于watch,所以加!this.initiated
      this.touch.initiated = true
      this.touch.startX = e.touches[0].pageX
//存储当前黄色进度条宽度
      this.touch.left = this.$refs.progress.clientWidth
    },
    progressTouchMove(e) {
      if (!this.touch.initiated) {
        return
      }
      const deltaX = e.touches[0].pageX - this.touch.startX
      //临界值:最大值是黄色进度条父元素宽度  this.$refs.progressBar.clientWidth
      //大于0
      const offsetWidth = Math.min(this.$refs.progressBar.clientWidth - progressBtnWidth, Math.max(0, this.touch.left + deltaX))
      //得出距离后,黄色进度条位置、小圆圈位置
      this._offset(offsetWidth)
    },
    progressTouchEnd(e) {
      this.touch.initiated = false
      //告诉外部拖动的百分比percent
      this._triggerPercent()
    },

3.4告知外部百分比

 _triggerPercent() {
  //this.$refs.progressBar.clientWidth 不带单位 px
  //this.$refs.progress.style.width 带单位px
  const barWidth = this.$refs.progressBar.clientWidth - progressBtnWidth
  const percent = this.$refs.progress.clientWidth / barWidth
  this.$emit('percentChange', percent)
},

在play.vue中联动

onProgressBarChange(percent) {
//根据百分比算出当前播放时间
  const currentTime = this.currentSong.duration * percent
//赋值给audio
  this.currentTime = this.$refs.audio.currentTime = currentTime
//如果未播放,则播放
  if (!this.playing) {
    this.togglePlaying()
  }
//同时歌词联动
  if (this.currentLyric) {
    //拖动进度条,歌词联动
    this.currentLyric.seek(currentTime * 1000)
  }
},

3.5点击进度条

progressClick(e) {
  const rect = this.$refs.progressBar.getBoundingClientRect()
  const offsetWidth = e.pageX - rect.left
//得出距离后,黄色进度条位置、小圆圈位置
  this._offset(offsetWidth)
//告诉外部拖动的百分比percent
  this._triggerPercent()
},

4. mini播放器进度条:圆形进度调组件ProgressCircle

利用svg以及进度percent做的进度条
props:

  • radius:svg宽高,相当于屏幕宽高
  • precent: 歌曲播放百分比
<div class="progress-circle">
    <svg :width="radius" :height="radius" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
      <circle class="progress-background" r="50" cx="50" cy="50" fill="transparent" />
      <!-- r表示半径,cx 和 cy 属性定义圆点的 x 和 y 坐标 fill表示背景色 -->
      <circle class="progress-bar" r="50" cx="50" cy="50" fill="transparent"
      :stroke-dasharray="dashArray" :stroke-dashoffset="dashOffset"/>
    </svg>
    <slot></slot>
  </div>
data () {
    return {
      dashArray: Math.PI * 100  圆的周长
    }
  },
  computed: {
    dashOffset() {
      return (1 - this.percent) * this.dashArray
    }
  },

css

.progress-circle
  position: relative
  circle
    stroke-width: 8px
    transform-origin: center
    &.progress-background
      transform: scale(0.9)
      stroke: $color-theme-d
    &.progress-bar
      //stroke-dashoffset一个特别之处是:它的起点是垂直居中,水平方向为右。为了得到想要的效果,有必要对圆形进行负值的旋转。
      transform: scale(0.9) rotate(-90deg)
      stroke: $color-theme

svg属性

  • viewBox:就是截屏工具选中的那个框框,最终的呈现就是把框框中的截屏内容再次在显示器中全屏显示
  • stroke-dasharray:这个属性就像border-style: dashed,但它可以让你定义破折号的宽度和它们之间的距离。
  • stroke-dashoffset:这个属性允许你沿着SVG元素的路径移动这个dash-gap序列的起始点。
    原文作者:云深不知处
    原文地址: https://segmentfault.com/a/1190000017028900
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞