小程序音频播放圆形进度条

最近,因为业务需要,研究了一波圆形进度条的实现,最终采用了如下这种方式。


先上效果图:


sound.gif

实现思路

  • 重点参照了 详解用CSS3制作圆形滚动进度条动画效果 的第三种效果。即采用两个矩形截取完整的两个圆,利用.progress_wrapperoverflow: hidden;属性防止整圆溢出,表现为两个半圆拼接为一个整圆。然后旋转矩形里面的圆,通过改变旋转角度逐渐显示隐藏的圆形部分,表现为音频进度条的变化。
  • 另外,这个圆形进度条有点小bug,在两个半圆下方接口处会有一像素的空隙,我采用了一像素背景图配合绝对定位填补这个空隙

WXML代码

核心圆形进度条wxml代码


  
    
      
    
    
      
    
    
    
  

WXSS代码

圆形进度条样式

.circle_container {
  position: absolute;
  width: 56rpx;
  height: 56rpx;
  right: 30rpx;
  bottom: 20rpx;
}

.circle_wrapper {
  position: relative;
  width: 56rpx;
  height: 56rpx;
}

.progress_wrapper {
  width: 28rpx;
  height: 56rpx;
  position: absolute;
  top: 0;
  overflow: hidden;
}

.circle_right {
  right: 0;
}

.circle_left {
  left: 0;
}

.circle_progress {
  width: 48rpx;
  height: 48rpx;
  border: 4rpx solid #fff;
  border-radius: 50%;
  position: absolute;
  top: 0;
  transform: rotate(45deg);
}

.right_circle {
  border-top: 4rpx solid transparent;
  border-right: 4rpx solid transparent;
  right: 0;
}

.left_circle {
  border-bottom: 4rpx solid transparent;
  border-left: 4rpx solid transparent;
  left: 0;
}

.circle_markup {
  position: absolute;
  left: 28rpx;
  bottom: 0;
  width: 2rpx;
  height: 4rpx;
  background: #fff;
  visibility: hidden;
}

JS代码

使用了WePY框架,其中,formatNumber格式化时间样式,isPlay控制音频播放图标,isStop控制播放悬浮框是否显示,time表示音频当前播放时间,duration表示音频总时长,percent表示音频进度条,play控制悬浮框音频播放图标,title表示音频标题,rightDeg表示右侧半圆旋转角度,leftDeg表示左侧半圆旋转角度,visible控制圆形进度条空隙是否显示

import wepy from 'wepy'
  import {
    formatNumber
  } from '@/utils/util'
  export default class Index extends wepy.page {
    config = {
      navigationBarTitleText: '测试'
    }
    data = {
      isPlay: false,
      isStop: true,
      duration: '',
      percent: 0,
      play: true,
      title: '今日片尾',
      time: '',
      rightDeg: '',
      leftDeg: '',
      visible: 'hidden'
    }
    methods = {
      play_audio_func() {
        const audio = wx.getBackgroundAudioManager()
        audio.src = 'http://audio.heardtech.com/endAudio.mp3'
        audio.title = '今日片尾'
      }
    }
    onLoad() {
      let leftDeg = ''
      let rightDeg = ''
      let visible = ''
      let currentTime = 0
      let duration = 0
      const audio = wx.getBackgroundAudioManager()
      audio.onPlay(() => {
        this.isPlay = true
        this.isStop = false
      })
      audio.onPause(() => {
        this.isPlay = false
        this.isStop = false
      })
      audio.onStop(() => {
        this.isPlay = false
        this.isStop = true
      })
      audio.onEnded(() => {
        // audio.onTimeUpdate(() => {})
        this.percent = 0
        this.isPlay = false
        this.isStop = true
      })
      audio.onError((e) => {
        console.log('音频播放错误', e)
      })
      audio.onTimeUpdate(() => {
        let audioData = this.computePercent(audio)
        this.percent = audioData.percent
        this.time = audioData.time
        currentTime = audioData.currentTime
        duration = audioData.duration
        this.duration = audioData.dtime
        // 右侧半圆在进度超过一半之后要保持旋转225deg状态,未超过一半,左侧半圆保持原始角度45deg
        if (currentTime / duration <= 0.5) {
          leftDeg = '45deg'
          rightDeg = currentTime / duration * 360 + 45 + 'deg'
          visible = 'hidden'
        } else {
          leftDeg = currentTime / duration * 360 + 225 + 'deg'
          rightDeg = '225deg'
          visible = 'visible'
        }

        this.rightDeg = rightDeg
        this.leftDeg = leftDeg
        this.visible = visible

        this.$apply()
      })
    }
    computePercent(audio) {
      let currentTime = parseInt(audio.currentTime)
      let duration = parseInt(audio.duration)
      let min = parseInt(currentTime / 60)
      let sec = parseInt(currentTime % 60)
      let dmin = parseInt(duration / 60)
      let dsec = parseInt(duration % 60)
      let time = formatNumber(min) + ':' + formatNumber(sec)
      let dtime = formatNumber(dmin) + ':' + formatNumber(dsec)
      let percent = parseInt(currentTime / duration * 100)
      console.log('currentTime:', currentTime, 'percent:', percent, 'duration:', duration)
      return {
        time,
        dtime,
        percent,
        currentTime,
        duration
      }
    }
  }

你可能感兴趣的:(小程序音频播放圆形进度条)