微信小程序自定义音频播放器---slider + wx.createInnerAudioContext()

话不多说,做出来的效果图是这样的


image.png

从上个页面直接返回了40条语音课程的列表(本地缓存),跳转页面时拿下标利用下标去拿音频对象。这是wxml的代码

<view class="container">
    <view class="audio">
        <!-- 课程的banner图片 -->
        <image class="poster" src="{{ imgUrl + poster }}"></image>
        <text class="name">{{media.name}}</text>
        <!-- 播放进度条 -->
        <view class="progress">
            <view class="controls">
                <text class="current">{{currentSecond}}</text>
                <view class="section section_gap">
                    <view class="body-view">
                        <slider disabled="true" min="0" max="{{duration}}" value="{{curSecond}}" activeColor="#F91C55" block-size="18"/>
                    </view>
                </view>
                <text class="total">{{media.timeLong}}</text>
            </view>
        </view>
        <!-- 播放控件 -->
        <view class="btns">
            <image class="previous" src="/images/emotion/previous.png" bindtap="previousFun"></image>
            <label class="play">
                <image src="{{ playing == true ? '/images/emotion/playing.png' : '/images/emotion/stop.png'}}" bindtap="playClick"></image>
            </label>
            <image class="next" src="/images/emotion/next.png" bindtap="nextFun"></image>
        </view>
    </view>
</view>

踩坑:

1.slider里面的 value / min / max 都必须是整数!!!(在innerAudioContext.onTimeUpdate()里面拿到innerAudioContext.currentTime和innerAudioContext.duration都是小数,需Math.ceil()向上取整再赋值)

2.如果把 innerAudioContext.onPlay、onStop、onPause、onTimeUpdate、onEnded、onError监听音频的事件写在onLoad里面只执行一次,在我点击上一首、下一首时再点击播放时,因为监听不到导致curSecond不变,slider的value不变进度条不动(解决方法:封装innerAudioContext部分监听,每次点击调用)

js部分

const app = getApp();
// 创建内部 audio 上下文 InnerAudioContext 对象
var innerAudioContext = wx.createInnerAudioContext()

// 时间格式化
function format(t) {
  let time = Math.floor(t / 60) >= 10 ? Math.floor(t / 60) : '0' + Math.floor(t / 60)
  t = time + ':' + ((t % 60) / 100).toFixed(2).slice(-2)
  return t
}

// 音频对象
function audio(media) {
  innerAudioContext = wx.createInnerAudioContext()
  innerAudioContext.src = app.globalData.globalUrl + media.url;
  innerAudioContext.obeyMuteSwitch = false;
  innerAudioContext.autoplay = false;
}

Page({
  /**
   * 页面的初始数据
   */
  data: {
    rId: null, //课程的id--添加记录时需要
    curIndex: null, //音频当前下标
    media: null, //音频信息对象
    poster: '',  //音频海报
    imgUrl: app.globalData.globalUrl,  //多媒体公共路径
    currentSecond: '00:00', //页面所需当前播放的时间
    curSecond: 0, // 当前播放的秒数
    duration: null,  //音频总时长
    playing: false //是否正在播放
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    // 从本地存储拿到文件信息、slider滑块的当前/总时长的换算
    this.data.poster = options.url;
    this.data.rId = options.rId;
    this.data.curIndex = Number(options.index);
    this.data.media = wx.getStorageSync('catalogList')[this.data.curIndex];
    this.setData({
      rId: this.data.rId,
      media: this.data.media,
      poster: this.data.poster,
      curIndex: this.data.curIndex
    })
    this.watchAudio();  //初始化调用一次
  },

  // 点击控件中间按键---播放/暂停
  playClick: function () {
    if (this.data.playing) {
      this.data.playing = false;
      this.setData({
        playing: this.data.playing
      })
      innerAudioContext.pause();
      return;
    } else {
      this.data.playing = true;
      this.setData({
        playing: this.data.playing
      })
      innerAudioContext.play();
      return;
    }
  },

  // 上一首
  previousFun: function () {
    if (this.data.curIndex == 0) {
      wx.showToast({
        title: '这就是第一课哟~',
        icon: "none"
      })
      return;
    } else {
      this.data.curIndex -= 1;
      this.data.playing = false;
      this.data.media = wx.getStorageSync('catalogList')[this.data.curIndex];
      this.data.curSecond = 0;
      this.data.currentSecond = format(0);
      this.setData({
        media: this.data.media,
        playing: this.data.playing,
        curIndex: this.data.curIndex,
        curSecond: this.data.curSecond,
        currentSecond: this.data.currentSecond
      })
      //重新调用音频
      innerAudioContext.stop();
      this.watchAudio();
    }
  },

  // 下一首
  nextFun: function () {
    if (this.data.curIndex == wx.getStorageSync('catalogList').length - 1) {
      wx.showToast({
        title: '这就是最后一课哟~',
        icon: "none"
      })
      return;
    } else {
      this.data.curIndex += 1;
      this.data.playing = false;
      this.data.media = wx.getStorageSync('catalogList')[this.data.curIndex];
      this.data.curSecond = 0;
      this.data.currentSecond = format(0);
      this.setData({
        media: this.data.media,
        playing: this.data.playing,
        curIndex: this.data.curIndex,
        curSecond: this.data.curSecond,
        currentSecond: this.data.currentSecond
      })
      //重新调用音频
      innerAudioContext.stop();
      this.watchAudio();
    }
  },

  // 监听audio
  watchAudio: function () {
    let that = this;
    audio(that.data.media);  //重新赋值音频对象
    //开始
    innerAudioContext.onPlay(() => {
      that.setData({
        playing: true
      })
    })
    //停止
    innerAudioContext.onStop(() => {
      that.setData({
        playing: false
      })
    })
    //暂停
    innerAudioContext.onPause(() => {
      that.setData({
        playing: false
      })
    })
    //播放进度
    innerAudioContext.onTimeUpdate(() => {
      that.data.duration = Math.ceil(innerAudioContext.duration);
      that.data.curSecond = Math.ceil(innerAudioContext.currentTime);
      that.data.currentSecond = format(innerAudioContext.currentTime);
      that.setData({
        duration: that.data.duration,
        curSecond: that.data.curSecond,
        currentSecond: that.data.currentSecond
      })
    })
    //播放结束
    innerAudioContext.onEnded(() => {
      that.setData({
          playing: false
      })
      that.nextFun();  //调用下一首
    })
    //播放错误
    innerAudioContext.onError((res) => {
      wx.showToast({
        title: '错误:' + res.errMsg,
        icon: "none"
      })
    })
  },
  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {
    // 停止音频播放
    innerAudioContext.stop(); 
    this.setData({ 
      playing: false      
    })
  },
}

以上代码仅供参考,入行不到两年,请多指教共同进步哟~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容