UNPKG

olympus-r

Version:

一个力求简单易用的前端开发框架 #### 开发语言 TypeScript #### 核心架构 MVC #### 模块间通讯和解耦 采用事件机制,利用一个全局唯一的事件派发器进行模块间通讯,解耦模块间依赖 #### 表现层结构 使用桥接模式拆分接口与实现,达到一套核心驱动多套表现层的目的(目前支持DOM、Egret、PixiJS三种表现层),同时支持表现层的未来可扩展性 #### TypeScript装饰器注入 框架提供TypeScript装饰器注入功能,便捷获取托管对象。例如:

310 lines (309 loc) 11.8 kB
import { core } from "../../core/Core"; import { assetsManager } from "../assets/AssetsManager"; import { environment } from "../env/Environment"; import { system } from "../system/System"; import AudioMessage from "./AudioMessage"; /** * @author Raykid * @email initial_r@qq.com * @create date 2017-10-30 * @modify date 2017-10-30 * * 使用AudioContext实现IAudio接口的实现类 */ var AudioContextImpl = /** @class */ (function () { function AudioContextImpl() { var _this = this; this._disposed = false; this._mute = false; this._playingDict = {}; this._audioCache = {}; this._onInit = null; this._context = new (window["AudioContext"] || window["webkitAudioContext"])(); this._onInit = function () { window.removeEventListener("touchstart", _this._onInit, true); window.removeEventListener("mousedown", _this._onInit, true); _this._onInit = null; // 生成一个空的音频,播放并停止,用以解除限制 var source = _this._context.createBufferSource(); source.buffer = _this._context.createBuffer(1, 1, 44100); source.connect(_this._context.destination); source.start(); source.stop(); // 要先挂起 _this._context.suspend(); // 如果当前有正在播放的音频,全部再播放一次 for (var url in _this._audioCache) { var data = _this._audioCache[url]; if (data.status == AudioStatus.PLAYING) { // 停止播放 _this.stop(data.playParams.url); // 重新播放 _this.play(data.playParams); } } }; // 这里监听触摸事件,一定要使用捕获阶段,否则会被某些框架阻止,比如egret window.addEventListener("touchstart", this._onInit, true); window.addEventListener("mousedown", this._onInit, true); } Object.defineProperty(AudioContextImpl.prototype, "disposed", { get: function () { return this._disposed; }, enumerable: true, configurable: true }); Object.defineProperty(AudioContextImpl.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 }); /** * 加载音频 * * @param {string} url 音频地址 * @memberof AudioContextImpl */ AudioContextImpl.prototype.load = function (url) { var _this = this; var toUrl = environment.toCDNHostURL(url); // 尝试获取缓存数据 var data = this._audioCache[toUrl]; // 如果没有缓存才去加载 if (!data) { // 使用AudioContext加载 this._audioCache[toUrl] = data = { buffer: null, status: AudioStatus.LOADING, playParams: null, progress: null }; // 派发加载开始事件 core.dispatch(AudioMessage.AUDIO_LOAD_STARTED, url); // 开始加载 assetsManager.loadAssets(toUrl, function (result) { if (result instanceof ArrayBuffer) { _this._context.decodeAudioData(result, function (buffer) { data.buffer = buffer; // 设置状态 data.status = AudioStatus.PAUSED; // 派发加载完毕事件 core.dispatch(AudioMessage.AUDIO_LOAD_ENDED, url); // 如果自动播放则播放 if (data.playParams) _this.play(data.playParams); }); } }, "arraybuffer"); } }; /** * 播放音频,如果音频没有加载则先加载再播放 * * @param {AudioPlayParams} params 音频播放参数 * @returns {void} * @memberof AudioContextImpl */ AudioContextImpl.prototype.play = function (params) { var _this = this; 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.status = AudioStatus.PLAYING; // 记录播放中 this._playingDict[toUrl] = params; // 已经加载完毕,直接播放 data.node = this._context.createBufferSource(); data.node.buffer = data.buffer; if (params.loop != null) data.node.loop = params.loop; data.node.connect(this._context.destination); // 监听播放完毕 data.node.onended = function () { var data = _this._audioCache[toUrl]; if (data) { // 停止播放 _this.stop(params.url); // 派发播放完毕事件 core.dispatch(AudioMessage.AUDIO_PLAY_ENDED, params.url, params); } }; // 要播放之前要起用 this._context.resume(); // 开始播放,优先取参数中的时间,没有就取默认开始时间 var playTime; if (params && params.time != null) playTime = params.time * 0.001; else playTime = data.playTime; delete data.playTime; data.node.start(playTime); // 开始播放进度监测 var lastTime = this._context.currentTime; var curTime = playTime || 0; data.progress = system.enterFrame(function () { var nowTime = _this._context.currentTime; var deltaTime = nowTime - lastTime; lastTime = nowTime; if (data.status == AudioStatus.PLAYING) { curTime += deltaTime * 1000; var totalTime = data.node.buffer.duration * 1000; core.dispatch(AudioMessage.AUDIO_PLAY_PROGRESS, params.url, curTime, totalTime, params); } }); // 派发播放开始事件 core.dispatch(AudioMessage.AUDIO_PLAY_STARTED, params.url, params); break; } } }; AudioContextImpl.prototype._doStop = function (url, time) { var toUrl = environment.toCDNHostURL(url); var data = this._audioCache[toUrl]; if (data) { // 设置状态 data.status = AudioStatus.PAUSED; // 取消进度监测 data.node.onended = null; if (data.progress) data.progress.cancel(); // 结束播放 if (data.node) { try { // 这里可能会报错,需要try cath data.node.stop(time); // 停止播音频时需要挂起 this._context.suspend(); } catch (err) { console.warn(err); } // 派发播放停止事件 core.dispatch(AudioMessage.AUDIO_PLAY_STOPPED, url, data.playParams); } } }; /** * 暂停音频(不会重置进度) * * @param {string} url 音频URL * @memberof AudioContextImpl */ AudioContextImpl.prototype.pause = function (url) { this._doStop(url); // 移除播放中 var toUrl = environment.toCDNHostURL(url); delete this._playingDict[toUrl]; }; /** * 停止音频(会重置进度) * * @param {string} url 音频URL * @memberof AudioContextImpl */ AudioContextImpl.prototype.stop = function (url) { this._doStop(url, 0); // 移除播放中 var toUrl = environment.toCDNHostURL(url); delete this._playingDict[toUrl]; }; /** * 停止所有音频 * * @memberof AudioContextImpl */ AudioContextImpl.prototype.stopAll = function () { for (var url in this._audioCache) { this.stop(url); } }; /** * 跳转音频进度 * * @param {string} url 音频URL * @param {number} time 要跳转到的音频位置,毫秒值 * @memberof AudioContextImpl */ AudioContextImpl.prototype.seek = function (url, time) { var toUrl = environment.toCDNHostURL(url); var data = this._audioCache[toUrl]; if (data) { var params = data.playParams; if (data.status == AudioStatus.PLAYING) { // 停止重新播放 this.stop(url); params.time = time; this.play(params); } else { data.playTime = time; } } }; AudioContextImpl.prototype.dispose = function () { if (!this._disposed) { if (this._onInit) { window.removeEventListener("touchstart", this._onInit, true); window.removeEventListener("mousedown", this._onInit, true); this._onInit = null; } this.stopAll(); this._disposed = true; } }; return AudioContextImpl; }()); export default AudioContextImpl; var AudioStatus; (function (AudioStatus) { /** * 加载中 */ AudioStatus[AudioStatus["LOADING"] = 0] = "LOADING"; /** * 已暂停 */ AudioStatus[AudioStatus["PAUSED"] = 1] = "PAUSED"; /** * 播放中 */ AudioStatus[AudioStatus["PLAYING"] = 2] = "PLAYING"; })(AudioStatus || (AudioStatus = {}));