1 /** 2 * Hilo 3 * Copyright 2015 alibaba.com 4 * Licensed under the MIT License 5 */ 6 7 /** 8 * @class HTMLAudio声音播放模块。此模块使用HTMLAudioElement播放音频。 9 * 使用限制:iOS平台需用户事件触发才能播放,很多Android浏览器仅能同时播放一个音频。 10 * @param {Object} properties 创建对象的属性参数。可包含此类所有可写属性。 11 * @module hilo/media/HTMLAudio 12 * @requires hilo/core/Hilo 13 * @requires hilo/core/Class 14 * @requires hilo/event/EventMixin 15 * @property {String} src 播放的音频的资源地址。 16 * @property {Boolean} loop 是否循环播放。默认为false。 17 * @property {Boolean} autoPlay 是否自动播放。默认为false。 18 * @property {Boolean} loaded 音频资源是否已加载完成。只读属性。 19 * @property {Boolean} playing 是否正在播放音频。只读属性。 20 * @property {Number} duration 音频的时长。只读属性。 21 * @property {Number} volume 音量的大小。取值范围:0-1。 22 * @property {Boolean} muted 是否静音。默认为false。 23 */ 24 var HTMLAudio = Class.create(/** @lends HTMLAudio.prototype */{ 25 Mixes: EventMixin, 26 constructor: function(properties){ 27 Hilo.copy(this, properties, true); 28 29 this._onAudioEvent = this._onAudioEvent.bind(this); 30 }, 31 32 src: null, 33 loop: false, 34 autoPlay: false, 35 loaded: false, 36 playing: false, 37 duration: 0, 38 volume: 1, 39 muted: false, 40 41 _element: null, //HTMLAudioElement对象 42 43 /** 44 * 加载音频文件。 45 */ 46 load: function(){ 47 if(!this._element){ 48 try{ 49 var elem = this._element = new Audio(); 50 elem.addEventListener('canplaythrough', this._onAudioEvent, false); 51 elem.addEventListener('ended', this._onAudioEvent, false); 52 elem.addEventListener('error', this._onAudioEvent, false); 53 elem.src = this.src; 54 elem.volume = this.volume; 55 elem.load(); 56 } 57 catch(err){ 58 //ie9 某些版本有Audio对象,但是执行play,pause会报错! 59 var elem = this._element = {}; 60 elem.play = elem.pause = function(){ 61 62 }; 63 } 64 } 65 return this; 66 }, 67 68 /** 69 * @private 70 */ 71 _onAudioEvent: function(e){ 72 // console.log('onAudioEvent:', e.type); 73 var type = e.type; 74 75 switch(type){ 76 case 'canplaythrough': 77 e.target.removeEventListener(type, this._onAudioEvent); 78 this.loaded = true; 79 this.duration = this._element.duration; 80 this.fire('load'); 81 if(this.autoPlay) this._doPlay(); 82 break; 83 case 'ended': 84 this.playing = false; 85 this.fire('end'); 86 if(this.loop) this._doPlay(); 87 break; 88 case 'error': 89 this.fire('error'); 90 break; 91 } 92 }, 93 94 /** 95 * @private 96 */ 97 _doPlay: function(){ 98 if(!this.playing){ 99 this._element.volume = this.muted ? 0 : this.volume; 100 this._element.play(); 101 this.playing = true; 102 } 103 }, 104 105 /** 106 * 播放音频。如果正在播放,则会重新开始。 107 * 注意:为了避免第一次播放不成功,建议在load音频后再播放。 108 */ 109 play: function(){ 110 if(this.playing) this.stop(); 111 112 if(!this._element){ 113 this.autoPlay = true; 114 this.load(); 115 }else if(this.loaded){ 116 this._doPlay(); 117 } 118 119 return this; 120 }, 121 122 /** 123 * 暂停音频。 124 */ 125 pause: function(){ 126 if(this.playing){ 127 this._element.pause(); 128 this.playing = false; 129 } 130 return this; 131 }, 132 133 /** 134 * 恢复音频播放。 135 */ 136 resume: function(){ 137 if(!this.playing){ 138 this._doPlay(); 139 } 140 return this; 141 }, 142 143 /** 144 * 停止音频播放。 145 */ 146 stop: function(){ 147 if(this.playing){ 148 this._element.pause(); 149 this._element.currentTime = 0; 150 this.playing = false; 151 } 152 return this; 153 }, 154 155 /** 156 * 设置音量。注意: iOS设备无法设置音量。 157 */ 158 setVolume: function(volume){ 159 if(this.volume != volume){ 160 this.volume = volume; 161 this._element.volume = volume; 162 } 163 return this; 164 }, 165 166 /** 167 * 设置静音模式。注意: iOS设备无法设置静音模式。 168 */ 169 setMute: function(muted){ 170 if(this.muted != muted){ 171 this.muted = muted; 172 this._element.volume = muted ? 0 : this.volume; 173 } 174 return this; 175 }, 176 177 Statics: /** @lends HTMLAudio */ { 178 /** 179 * 浏览器是否支持HTMLAudio。 180 */ 181 isSupported: window.Audio !== null 182 } 183 184 });