UNPKG

captain-ui

Version:

有赞vue wap业务组件库

281 lines (255 loc) 7.41 kB
import Vue from 'vue'; var STATUS = { STOP: 0, PLAY: 1, PAUSE: 2 }; var FORWARD_BACK_STEP = 10; export default { render: function render() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c('div', { staticClass: "cap-audio-controller" }, [_vm._t("default", null, { audioEventBus: _vm.audioEventBus, percentage: _vm.percentage, formatedCurrentTime: _vm.formatedCurrentTime, formatedDuration: _vm.formatedDuration, loadedPercentage: _vm.loadedPercentage, loadedStartPercentage: _vm.loadedStartPercentage, isPlaying: _vm.isPlaying, isStop: _vm.isStop, isPause: _vm.isPause, isLoading: _vm.isLoading, isLoaded: _vm.isLoaded })], 2); }, name: 'cap-audio-controller', props: { audioUrl: { type: String, default: '' }, audioTitle: { type: String, default: '' }, audioDuration: Number, preload: { type: String, default: 'none' }, loop: { type: Boolean, default: false } }, data: function data() { return { percentage: 0, loadedPercentage: 0, loadedStartPercentage: 0, status: STATUS.STOP, currentTime: 0, duration: 0, audio: null, audioEventBus: null, isLoading: false, isLoaded: false }; }, computed: { isPlaying: function isPlaying() { return this.status === STATUS.PLAY; }, isStop: function isStop() { return this.status === STATUS.STOP; }, isPause: function isPause() { return this.status === STATUS.PAUSE; }, formatedCurrentTime: function formatedCurrentTime() { return this.getTime(this.currentTime); }, formatedDuration: function formatedDuration() { return this.getTime(this.duration); } }, watch: { audioUrl: function audioUrl(val) { this.resetAudio(); this.destroy(); this.loadAudio(val); } }, created: function created() { this.loadAudio(this.audioUrl); this.initComponentAudioEvent(); }, methods: { /** * 小于10的数左边补0 * @param {number} number 需要补0的数 * @return {string} 处理后的结果 */ pad: function pad(number) { return number < 10 ? "0" + number : "" + number; }, /** * 将秒数转化为“分:秒”的形式 * @param {number} seconds 秒数 * @return {string} 转化结果 */ getTime: function getTime(seconds) { var minute = parseInt(seconds / 60, 10); var second = parseInt(seconds % 60); return this.pad(minute) + ":" + this.pad(second); }, /** * 播放音频 */ play: function play() { if (!this.audio) { this.$emit('no-audio'); return; } this.audio.play(); this.status = STATUS.PLAY; this.$emit('audio-play'); }, /** * 暂停音频 */ pause: function pause() { if (!this.audio) return; this.audio.pause(); this.status = STATUS.PAUSE; this.$emit('audio-pause'); }, /** * 停止播放 */ stop: function stop() { if (!this.audio) return; this.audio.pause(); this.status = STATUS.STOP; this.audio.currentTime = 0; this.$emit('audio-stop'); }, /** * 快进 */ forward: function forward() { if (!this.audio) return; this.audio.currentTime += FORWARD_BACK_STEP; this.$emit('audio-forward'); }, /** * 快退 */ back: function back() { if (!this.audio) return; this.audio.currentTime -= FORWARD_BACK_STEP; this.$emit('audio-back'); }, /** * 重播音频 */ replay: function replay() { if (!this.audio) return; this.audio.currentTime = 0; this.play(); }, /** * 重置音频 */ resetAudio: function resetAudio() { if (!this.audio) return; this.pause(); this.audio.currentTime = 0; this.status = STATUS.STOP; }, /* * 销毁音频 */ destroy: function destroy() { this.pause(); this.audio = null; }, /** * 播放进度跳转 * @param {number} percentage 播放进度百分比 */ updateProgress: function updateProgress(percentage) { if (!this.audio) return; this.audio.currentTime = parseInt(this.duration * percentage / 100); }, // 更新音频离当前播放时间最近的加载起点和加载进度 updateLoadedPercentage: function updateLoadedPercentage() { var range = 0; var buffer = this.audio.buffered; var time = this.audio.currentTime; if (!buffer.length) return; // 取当前播放时间所在的那段buffer while (range < buffer.length && !(buffer.start(range) <= time && time <= buffer.end(range))) { range += 1; } var loadedStartPercentage = buffer.start(range) / this.durationSeconds * 100; var loadedEndPercentage = buffer.end(range) / this.durationSeconds * 100; var loadedPercentage = loadedEndPercentage - loadedStartPercentage; this.loadedStartPercentage = loadedStartPercentage; this.loadedPercentage = loadedPercentage; }, loadAudio: function loadAudio(url) { var _this = this; if (!url) return; var audio = document.createElement('audio'); // 优先使用外部duration if (this.audioDuration) { this.duration = this.audioDuration; } else { audio.addEventListener('loadedmetadata', function () { _this.duration = audio.duration; }); } // 缓冲时显示loading audio.addEventListener('waiting', function () { _this.isLoading = true; }); // 可播放时隐藏loading audio.addEventListener('canplaythrough', function () { _this.isLoading = false; _this.isLoaded = true; }); // 下载进度更新时,更新已下载的进度条 audio.addEventListener('progress', function () { _this.updateLoadedPercentage(); }); // 更新时间轴 audio.addEventListener('timeupdate', function () { _this.currentTime = audio.currentTime; _this.percentage = Math.min(_this.currentTime / _this.duration * 100, 100); }); // 播放结束后重置播放状态 audio.addEventListener('ended', function () { _this.status = STATUS.PAUSE; _this.$emit('audio-end'); }); // 监听错误消息 audio.addEventListener('error', function (e) { _this.$emit('audio-error', e); }); audio.src = url; audio.title = this.audioTitle; audio.loop = this.loop; audio.preload = this.preload; this.audio = audio; }, initComponentAudioEvent: function initComponentAudioEvent() { var audioEventBus = new Vue(); audioEventBus.$on('audio:play', this.play); audioEventBus.$on('audio:pause', this.pause); audioEventBus.$on('audio:stop', this.stop); audioEventBus.$on('audio:forward', this.forward); audioEventBus.$on('audio:back', this.back); audioEventBus.$on('audio:replay', this.replay); audioEventBus.$on('audio:reset', this.reset); audioEventBus.$on('audio:progress:update', this.updateProgress); this.audioEventBus = audioEventBus; } } };