captain-ui
Version:
有赞vue wap业务组件库
290 lines (260 loc) • 7.63 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = void 0;
var _vue = _interopRequireDefault(require("vue"));
var STATUS = {
STOP: 0,
PLAY: 1,
PAUSE: 2
};
var FORWARD_BACK_STEP = 10;
var _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.default();
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;
}
}
};
exports.default = _default;