190 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			190 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
/**
 | 
						|
 * @fileoverview audio 组件
 | 
						|
 */
 | 
						|
const context = require('./context')
 | 
						|
 | 
						|
Component({
 | 
						|
  data: {
 | 
						|
    time: '00:00'
 | 
						|
  },
 | 
						|
  properties: {
 | 
						|
    name: String, // 音乐名
 | 
						|
    author: String, // 作者
 | 
						|
    poster: String, // 海报图片地址
 | 
						|
    autoplay: Boolean, // 是否自动播放
 | 
						|
    controls: Boolean, // 是否显示控件
 | 
						|
    loop: Boolean, // 是否循环播放
 | 
						|
    src: { // 源地址
 | 
						|
      type: String,
 | 
						|
      observer (src) {
 | 
						|
        this.setSrc(src)
 | 
						|
      }
 | 
						|
    }
 | 
						|
  },
 | 
						|
  created () {
 | 
						|
    // 创建内部 context
 | 
						|
    this._ctx = wx.createInnerAudioContext()
 | 
						|
    this._ctx.onError(err => {
 | 
						|
      this.setData({
 | 
						|
        error: true
 | 
						|
      })
 | 
						|
      this.triggerEvent('error', err)
 | 
						|
    })
 | 
						|
    this._ctx.onTimeUpdate(() => {
 | 
						|
      const time = this._ctx.currentTime
 | 
						|
      const min = parseInt(time / 60)
 | 
						|
      const sec = Math.ceil(time % 60)
 | 
						|
      const data = {}
 | 
						|
      data.time = (min > 9 ? min : '0' + min) + ':' + (sec > 9 ? sec : '0' + sec)
 | 
						|
      // 不在拖动状态下需要更新进度条
 | 
						|
      if (!this.lastTime) {
 | 
						|
        data.value = time / this._ctx.duration * 100
 | 
						|
      }
 | 
						|
      this.setData(data)
 | 
						|
    })
 | 
						|
    this._ctx.onEnded(() => {
 | 
						|
      if (!this.properties.loop) {
 | 
						|
        this.setData({
 | 
						|
          playing: false
 | 
						|
        })
 | 
						|
      }
 | 
						|
    })
 | 
						|
    // #ifndef ALIPAY
 | 
						|
  },
 | 
						|
  attached () {
 | 
						|
    context.set(this.id, this)
 | 
						|
    // #endif
 | 
						|
    // #ifdef MP-ALIPAY
 | 
						|
    context.set(this.properties.id, this)
 | 
						|
    this.setSrc(this.properties.src)
 | 
						|
    // #endif
 | 
						|
  },
 | 
						|
  // #ifdef MP-ALIPAY
 | 
						|
  didUpdate (e) {
 | 
						|
    if (e.src !== this.properties.src) {
 | 
						|
      this.setSrc(this.properties.src)
 | 
						|
    }
 | 
						|
  },
 | 
						|
  // #endif
 | 
						|
  detached () {
 | 
						|
    this._ctx.destroy()
 | 
						|
    // #ifndef MP-ALIPAY
 | 
						|
    context.remove(this.id)
 | 
						|
    // #endif
 | 
						|
    // #ifdef MP_ALIPAY
 | 
						|
    context.remove(this.properties.id)
 | 
						|
    // #endif
 | 
						|
  },
 | 
						|
  // #ifndef ALIPAY | TOUTIAO
 | 
						|
  pageLifetimes: {
 | 
						|
    show () {
 | 
						|
      // 播放被后台打断时,页面显示后自动继续播放
 | 
						|
      if (this.data.playing && this._ctx.paused) {
 | 
						|
        this._ctx.play()
 | 
						|
      }
 | 
						|
    }
 | 
						|
  },
 | 
						|
  // #endif
 | 
						|
  methods: {
 | 
						|
    /**
 | 
						|
     * @description 设置源
 | 
						|
     * @param {string} src 源地址
 | 
						|
     */
 | 
						|
    setSrc (src) {
 | 
						|
      this._ctx.autoplay = this.properties.autoplay
 | 
						|
      this._ctx.loop = this.properties.loop
 | 
						|
      this._ctx.src = src
 | 
						|
      if (this.properties.autoplay && !this.data.playing) {
 | 
						|
        this.setData({
 | 
						|
          playing: true
 | 
						|
        })
 | 
						|
      }
 | 
						|
    },
 | 
						|
 | 
						|
    /**
 | 
						|
     * @description 播放音乐
 | 
						|
     */
 | 
						|
    play () {
 | 
						|
      this._ctx.play()
 | 
						|
      this.setData({
 | 
						|
        playing: true
 | 
						|
      })
 | 
						|
      this.triggerEvent('play'
 | 
						|
        // #ifdef MP-ALIPAY
 | 
						|
        , {
 | 
						|
          target: {
 | 
						|
            id: this.props.id
 | 
						|
          }
 | 
						|
        }
 | 
						|
        // #endif
 | 
						|
      )
 | 
						|
    },
 | 
						|
 | 
						|
    /**
 | 
						|
     * @description 暂停音乐
 | 
						|
     */
 | 
						|
    pause () {
 | 
						|
      this._ctx.pause()
 | 
						|
      this.setData({
 | 
						|
        playing: false
 | 
						|
      })
 | 
						|
      this.triggerEvent('pause')
 | 
						|
    },
 | 
						|
 | 
						|
    /**
 | 
						|
     * @description 设置播放速率
 | 
						|
     * @param {Number} rate 播放速率
 | 
						|
     */
 | 
						|
    playbackRate (rate) {
 | 
						|
      this._ctx.playbackRate = rate
 | 
						|
    },
 | 
						|
 | 
						|
    /**
 | 
						|
     * @description 停止音乐
 | 
						|
     */
 | 
						|
    stop () {
 | 
						|
      this._ctx.stop()
 | 
						|
      this.setData({
 | 
						|
        playing: false,
 | 
						|
        time: '00:00'
 | 
						|
      })
 | 
						|
      this.triggerEvent('stop')
 | 
						|
    },
 | 
						|
 | 
						|
    /**
 | 
						|
     * @description 控制进度
 | 
						|
     * @param {number} sec 秒数
 | 
						|
     */
 | 
						|
    seek (sec) {
 | 
						|
      this._ctx.seek(sec)
 | 
						|
    },
 | 
						|
 | 
						|
    /**
 | 
						|
     * @description 移动进度条
 | 
						|
     * @param {event} e
 | 
						|
     * @private
 | 
						|
     */
 | 
						|
    _seeking (e) {
 | 
						|
      // 避免过于频繁 setData
 | 
						|
      if (e.timeStamp - this.lastTime < 200) return
 | 
						|
      const time = Math.round(e.detail.value / 100 * this._ctx.duration)
 | 
						|
      const min = parseInt(time / 60)
 | 
						|
      const sec = time % 60
 | 
						|
      this.setData({
 | 
						|
        time: (min > 9 ? min : '0' + min) + ':' + (sec > 9 ? sec : '0' + sec)
 | 
						|
      })
 | 
						|
      this.lastTime = e.timeStamp
 | 
						|
    },
 | 
						|
 | 
						|
    /**
 | 
						|
     * @description 进度条移动完毕
 | 
						|
     * @param {event} e
 | 
						|
     * @private
 | 
						|
     */
 | 
						|
    _seeked (e) {
 | 
						|
      this._ctx.seek(e.detail.value / 100 * this._ctx.duration)
 | 
						|
      this.lastTime = undefined
 | 
						|
    }
 | 
						|
  }
 | 
						|
})
 |