Skip to content

Instantly share code, notes, and snippets.

@vincenting
Last active December 12, 2015 00:28
Show Gist options
  • Save vincenting/4683784 to your computer and use it in GitHub Desktop.
Save vincenting/4683784 to your computer and use it in GitHub Desktop.
/**
* Author: Vincent Tin
* Date: 13-2-1
* Time: 上午11:43
*/
(function (window, document, $,_){
/**
* 用于处理拓词发音的封装包,其中ToVoice只能实例化一次,使用requireJs直接返回实例化对象
*/
var _getIdByWord , _isBadBrowser , loadedQueue={} , ToVoice;
/**
* 将单词发音的URL转化为ID
* @param fileUrl 需要转化的URL地址
* @return {String} 最后的ID字符串
* @private
*/
_getIdByWord = function(fileUrl){
var fileNamePieces = fileUrl.split('/'),
_fileName = fileNamePieces[fileNamePieces.length-1].split('.')[0];
return _fileName.replace(/-/g,'x').replace(/\$/g,'_').replace(/\s+/g,'_').replace(/\(/g,'_').replace(/\)/g,'_').replace(/'/,"_");
};
_isBadBrowser = (/**
*是否为VISTA以前的系统(主要针对XP),并且使用了IE内核的浏览器
* @return {Boolean}
* @private
*/
function(){
var _u = window.navigator.userAgent.toLowerCase(),_i = _u.indexOf("windows nt");
if(_i===-1){
return false;
}else{
try{
var _version = _u.substring(_i + 11, _i + 14);
return (_version < 6&&_u.indexOf('msie')!==-1);
}catch(e){
return true;
}
}
})();
/**
* @param user_config 自定义参数,为关联数组
* @param readyCallback 播放器初始化成功调用函数
* @constructor
*/
ToVoice = function(user_config,readyCallback){
this.init.apply(this,arguments);
};
ToVoice.fn = ToVoice.prototype;
/**
* @note 如果不是旧式浏览器,尝试使用SoundManager2来实现发音,初始化失败采用自带播放器播放
* 2013-2-18添加如果是MAC下无FLASH的情况,使用HTML5模式
*
*/
ToVoice.fn.init = function(userConfig,readyCallback){
readyCallback = readyCallback ? readyCallback : $.noop;
try{
if(navigator.userAgent.toLowerCase().indexOf("mac")!==-1&&!window.swfobject.ua.pv[0]){
this.setHtml5Mode.call(this,readyCallback);
return;
}
}catch(e) {}
this.setSMMode.apply(this);
var config = this.autoConfig.apply(this,arguments);
this.localSwfUrl = config.url;
if(!_isBadBrowser){
soundManager.setup(config);
}else{
this.setSWFMode.call(this,readyCallback);
}
};
/**
* @note 根据自定义配置最后产生SoundManager2的配置
*
*/
ToVoice.fn.autoConfig = function(userConfig,readyCallback){
var _this = this,
config = {
url: 'swf/',
flashVersion : 9,
preferFlash : true,
useFlashBlock : false,
useHighPerformance : true,
useFastPolling : true,
autoLoad : true,
debugMode:false,
onready: function(){
readyCallback.call(_this);
},
ontimeout: function() {
$("#sm2-container").remove();
_this.setSWFMode.call(_this,readyCallback);
}
};
_.map(userConfig,function(value,item){
config[item] = value;
});
return config;
};
/**
* 将播放器设置为HTML5模式
*/
ToVoice.fn.setHtml5Mode = function(readyCallback){
$("body").append("<div id = 'toVoiceSpeaker'></div><div id='toVoicePreLoad'></div>");
this.$speaker = $("#toVoiceSpeaker");
this.$preLoad = $("#toVoicePreLoad");
this.play = _h5Play;
this.preLoad = _h5PreLoad;
this.deleteDom = _swfDeleteDom;
this.destruct = _swfDestruct;
var _this = this;
setTimeout(function(){
readyCallback.apply(_this,arguments);
},50);
};
/**
* 将播放器设为使用soundManager2的播放模式
*/
ToVoice.fn.setSMMode = function(){
this.play = _smPlay;
this.preLoad = _smPreLoad;
this.deleteDom = _smDeleteDom;
this.destruct = _smDestruct;
};
/**
* 将播放器设为使用本地播放器的播放模式
*/
ToVoice.fn.setSWFMode = function(readyCallback){
$("body").append("<div id = 'toVoiceSpeaker'></div><div id='toVoicePreLoad'></div>");
this.play = _swfPlay;
this.preLoad = _swfPreLoad;
this.deleteDom = _swfDeleteDom;
this.destruct = _swfDestruct;
this.$speaker = $("#toVoiceSpeaker");
this.$preLoad = $("#toVoicePreLoad");
readyCallback.apply(this,arguments);
};
/**
* 使用HTML的方式播放
* @param url
* @private
*/
var _h5Play = function(url){
var audio = document.createElement('audio');
audio.src = url;
this.$speaker.html(audio);
audio.play();
};
/**
* 使用HTML的方式对单个URL进行预载入
* @param url
* @private
*/
var _h5LoadOne = function(url){
var audio = document.createElement('audio');
audio.src = url;
audio.id = _getIdByWord(url);
this.$preLoad[0].appendChild(audio);
audio.volume = 0;
audio.muted= true;
audio.preload="auto";
audio.play();
};
/**
* 使用HTML的方式对URL列表进行预载入
* @param list
* @private
*/
var _h5PreLoad = function(list){
if (!_.isArray(list)) list = [list];
_.each(list,_h5LoadOne,this);
};
/**
* 使用soundManager2进行播放
* @param url
* @private
*/
var _smPlay = function(url){
var mp3Id = _getIdByWord(url);
if(_.has(loadedQueue,mp3Id)){
loadedQueue[mp3Id].play();
}else{
/**
* @note 如果没有载入成功,将重新载入
*/
_preLoadOne(url,true);
}
};
/**
* 使用soundManager2对声音文件进行预先载入
* @param url 需要预先载入的MP3地址
* @param isAutoPlay 是否在载入后就进行播放
* @private
*/
var _preLoadOne = function(url,isAutoPlay){
if(soundManager.canPlayURL(url)){
var mp3Id = _getIdByWord(url),
tmpObject = soundManager.createSound({
id: mp3Id,
url: url,
autoLoad: true,
autoPlay: !!isAutoPlay,
onload: function() {
loadedQueue[mp3Id] = tmpObject;
}
});
}
};
/**
* 使用soundManager2对多个MP3进行预先载入
* @param list 需要预先载入的MP3地址列表
* @private
*/
var _smPreLoad = function(list){
if (!_.isArray(list)) list = [list];
_.each(list,function(url){
_preLoadOne(url,false);
});
};
/**
* 删除soundManager2中已经存在的对象
* @param url 需要删除的MP3地址
* @private
*/
var _smDeleteDom = function(url){
var mp3Id = _getIdByWord(url),
soundObj = soundManager.getSoundById(mp3Id);
if(soundObj){
soundObj.unload();
soundObj.destruct();
}
if(_.has(loadedQueue,mp3Id)){
delete loadedQueue[mp3Id];
}
};
/**
* 删除soundManager2中所有已经存在的对象
* @private
*/
var _smDestruct = function(){
_.map(loadedQueue, function (mp3Object,mp3Id) {
mp3Object.unload();
mp3Object.destruct();
delete loadedQueue[mp3Id];
});
};
/**
* 将MP3地址转化为可以播放的HTML字符串
* @param url MP3地址
* @param isPreLoad 是否载入模式
* @return {string}
* @private
*/
var _getSwfObject = function(url,isPreLoad){
//noinspection JSUnresolvedFunction
var localSwfUrl = this.localSwfUrl ,
swfTemplate = _.template('<embed id = "<%= mp3Id %>" wmode="transparent" type="application/x-shockwave-flash" width="1" height="1" pluginspage="http://www.macromedia.com/go/getflashplayer" menu="false" quality="high" src="<%= swfUrl %><% if(isPreLoad) {%>towords.loader.swf<% }else{ %>towords.speaker.swf<% } %>" FlashVars="url=<%= mp3Url %>&auto=1"/>');
return swfTemplate({
mp3Id : _getIdByWord(url) ,
swfUrl : localSwfUrl ,
mp3Url : url ,
'isPreLoad' : isPreLoad
});
};
/**
* 使用本地播放器播放MP3
* @param url MP3地址
* @private
*/
var _swfPlay = function(url){
var html = _getSwfObject.call(this,url,false);
this.$speaker.html(html);
};
/**
* @note 使用本地播放器生成HTML时缓存
*/
var temSwfList = [];
/**
* 使用本地播放器对系列MP3进行预先载入操作
* @param list 需要预先载入的MP3地址列表
* @private
*/
var _swfPreLoad = function(list){
if (!_.isArray(list)) list = [list];
temSwfList.length = 0;
_.each(list,function(url){
var html = _getSwfObject.call(this,url,true);
temSwfList.push(html);
},this);
this.$preLoad.append(temSwfList.join(""));
};
/**
* 删除Dom中MP3预先载入产生的DIV节点
* @param url 需要删除的MP3地址
* @private
*/
var _swfDeleteDom = function(url){
var mp3Id = _getIdByWord(url);
$("#"+mp3Id).remove();
};
/**
* 删除Dom中所有预先载入产生的DIV节点
* @private
*/
var _swfDestruct = function(){
this.$preLoad.html("");
};
/**
* @note 将ToVoice暴露在全局变量中
*/
window.ToVoice = ToVoice;
/**
* @note 如果使用了requireJs就返回ToVoice实例对象
*/
var toVoice = false;
if ( typeof define === "function" && define.amd) {
define(["config","soundManager"],
/**
* 根据ToVoice的实例化情况返回相应的匿名函数
* @param config 系统配置文件
* @return {Function}
*/
function (config) {
if(toVoice){
return function(callback){
if(_.isFunction(callback))callback.call(toVoice);
return toVoice;
}
}
return function(callback){
toVoice = new ToVoice({
url: config.swfUrl
},callback);
return toVoice;
};
}
);
}
}(window,document,jQuery,_));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment