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
 | |
|     }
 | |
|   }
 | |
| })
 |