olympus-r
Version:
一个力求简单易用的前端开发框架 #### 开发语言 TypeScript #### 核心架构 MVC #### 模块间通讯和解耦 采用事件机制,利用一个全局唯一的事件派发器进行模块间通讯,解耦模块间依赖 #### 表现层结构 使用桥接模式拆分接口与实现,达到一套核心驱动多套表现层的目的(目前支持DOM、Egret、PixiJS三种表现层),同时支持表现层的未来可扩展性 #### TypeScript装饰器注入 框架提供TypeScript装饰器注入功能,便捷获取托管对象。例如:
261 lines (260 loc) • 9.4 kB
JavaScript
import { core } from "../../core/Core";
import { environment } from "../env/Environment";
import AudioMessage from "./AudioMessage";
/**
* @author Raykid
* @email initial_r@qq.com
* @create date 2017-10-30
* @modify date 2017-10-30
*
* 使用Audio标签实现IAudio接口的实现类
*/
var AudioTagImpl = /** @class */ (function () {
function AudioTagImpl() {
this._disposed = false;
this._mute = false;
this._playingDict = {};
this._audioCache = {};
}
Object.defineProperty(AudioTagImpl.prototype, "disposed", {
get: function () {
return this._disposed;
},
enumerable: true,
configurable: true
});
Object.defineProperty(AudioTagImpl.prototype, "mute", {
/**
* 静音状态
*
* @type {boolean}
* @memberof AudioTagImpl
*/
get: function () {
return this._mute;
},
set: function (value) {
this._mute = value;
// 静音,暂停所有声音
for (var url in this._playingDict) {
if (value) {
// 静音,停止音频,不可调用stop方法,因为要保持播放中的音频状态
this._doStop(url);
}
else {
// 非静音,播放音频
var params = this._playingDict[url];
this.play(params);
}
}
},
enumerable: true,
configurable: true
});
AudioTagImpl.prototype.listenProgress = function (data) {
data.node.ontimeupdate = function (evt) {
// 只有播放状态可以派发PROGRESS事件
if (data.status == AudioStatus.PLAYING) {
// 我们规定使用毫秒值作为单位
var curTime = data.node.currentTime * 1000;
var totalTime = data.node.duration * 1000;
// 派发播放进度事件
core.dispatch(AudioMessage.AUDIO_PLAY_PROGRESS, data.playParams.url, curTime, totalTime, data.playParams);
}
};
};
/**
* 加载音频
*
* @param {string} url 音频地址
* @memberof AudioTagImpl
*/
AudioTagImpl.prototype.load = function (url) {
var _this = this;
var toUrl = environment.toCDNHostURL(url);
// 尝试获取缓存数据
var data = this._audioCache[toUrl];
// 如果没有缓存才去加载
if (!data) {
// 派发加载开始事件
core.dispatch(AudioMessage.AUDIO_LOAD_STARTED, url);
// 使用Audio标签加载
var node = document.createElement("audio");
// 这里强制使用autoplay,因为在IOS的safari上如果没这个参数,则根本不会触发onloadeddata事件
node.autoplay = true;
node.src = toUrl;
// 保存数据
this._audioCache[toUrl] = data = { node: node, status: AudioStatus.LOADING, playParams: null };
// 监听加载
node.onloadeddata = function () {
// 记录加载完毕
data.status = AudioStatus.PAUSED;
// 派发加载完毕事件
core.dispatch(AudioMessage.AUDIO_LOAD_ENDED, url);
// 如果不自动播放则暂停
if (!data.playParams) {
node.pause();
}
else {
var params = data.playParams;
// 设置状态
data.status = AudioStatus.PLAYING;
// 记录播放中
_this._playingDict[toUrl] = params;
// 派发播放开始事件
core.dispatch(AudioMessage.AUDIO_PLAY_STARTED, params.url, params);
// 监听播放进度
_this.listenProgress(data);
}
};
node.onended = function () {
_this.stop(url);
// 派发播放完毕事件
core.dispatch(AudioMessage.AUDIO_PLAY_ENDED, url, data.playParams);
// 如果循环则再开
if (data.playParams.loop)
_this.play(data.playParams);
};
node.onerror = function (evt) {
//派发错误事件
core.dispatch(AudioMessage.AUDIO_ERROR, url, evt);
};
}
};
/**
* 播放音频,如果音频没有加载则先加载再播放
*
* @param {AudioPlayParams} params 音频播放参数
* @returns {void}
* @memberof AudioTagImpl
*/
AudioTagImpl.prototype.play = function (params) {
var toUrl = environment.toCDNHostURL(params.url);
// 尝试获取缓存数据
var data = this._audioCache[toUrl];
if (!data) {
// 没有加载过,开始加载音频
this.load(params.url);
// 设置播放参数
this._audioCache[toUrl].playParams = params;
}
else {
switch (data.status) {
case AudioStatus.LOADING:
// 正在加载中,替换自动播放参数
data.playParams = params;
break;
case AudioStatus.PLAYING:
// 正在播放,关闭后再播放
this.stop(params.url);
this.play(params);
break;
case AudioStatus.PAUSED:
// 已经加载完毕,暂停中,直接播放
data.playParams = params;
if (params.stopOthers)
this.stopAll();
if (params.loop != null)
data.node.loop = params.loop;
if (params.time != null)
data.node.currentTime = params.time * 0.001;
// 监听播放进度
this.listenProgress(data);
// 开始播放,safari不支持直接play(WTF?)所以要用autoplay加load进行播放
data.node.autoplay = true;
data.node.load();
// 设置状态
data.status = AudioStatus.PLAYING;
// 记录播放中
this._playingDict[toUrl] = params;
// 派发播放开始事件
core.dispatch(AudioMessage.AUDIO_PLAY_STARTED, params.url, params);
break;
}
}
};
AudioTagImpl.prototype._doStop = function (url, time) {
var toUrl = environment.toCDNHostURL(url);
if (this._playingDict[toUrl]) {
var data = this._audioCache[toUrl];
data.node.autoplay = false;
data.node.pause();
// 设置停止时间
if (time != null)
data.node.currentTime = time * 0.001;
// 设置状态
data.status = AudioStatus.PAUSED;
// 派发播放停止事件
core.dispatch(AudioMessage.AUDIO_PLAY_STOPPED, url, data.playParams);
}
};
/**
* 暂停音频(不会重置进度)
*
* @param {string} url 音频URL
* @memberof AudioTagImpl
*/
AudioTagImpl.prototype.pause = function (url) {
this._doStop(url);
// 移除播放中
var toUrl = environment.toCDNHostURL(url);
delete this._playingDict[toUrl];
};
/**
* 停止音频(会重置进度)
*
* @param {string} url 音频URL
* @memberof AudioTagImpl
*/
AudioTagImpl.prototype.stop = function (url) {
this._doStop(url, 0);
// 移除播放中
var toUrl = environment.toCDNHostURL(url);
delete this._playingDict[toUrl];
};
/**
* 停止所有音频
*
* @memberof AudioTagImpl
*/
AudioTagImpl.prototype.stopAll = function () {
for (var url in this._audioCache) {
this.stop(url);
}
};
/**
* 跳转音频进度
*
* @param {string} url 音频URL
* @param {number} time 要跳转到的音频位置,毫秒值
* @memberof AudioTagImpl
*/
AudioTagImpl.prototype.seek = function (url, time) {
var data = this._audioCache[url];
if (data)
data.node.currentTime = time * 0.001;
};
AudioTagImpl.prototype.dispose = function () {
if (!this._disposed) {
this.stopAll();
this._disposed = true;
}
};
return AudioTagImpl;
}());
export default AudioTagImpl;
var AudioStatus;
(function (AudioStatus) {
/**
* 加载中
*/
AudioStatus[AudioStatus["LOADING"] = 0] = "LOADING";
/**
* 已暂停
*/
AudioStatus[AudioStatus["PAUSED"] = 1] = "PAUSED";
/**
* 播放中
*/
AudioStatus[AudioStatus["PLAYING"] = 2] = "PLAYING";
})(AudioStatus || (AudioStatus = {}));