1 /** 2 * Hilo 3 * Copyright 2015 alibaba.com 4 * Licensed under the MIT License 5 */ 6 7 /** 8 * @language=en 9 * @class HTMLAudio is an audio playing module, which uses HTMLAudioElement to play audio. 10 * Limits: iOS platform requires user action events to start playing, and many Android browser can only play one audio at a time. 11 * @param {Object} properties create object properties, include all writable properties of this class. 12 * @module hilo/media/HTMLAudio 13 * @requires hilo/core/Hilo 14 * @requires hilo/core/Class 15 * @requires hilo/event/EventMixin 16 * @property {String} src The source of the playing audio. 17 * @property {Boolean} loop Is loop playback, default value is false. 18 * @property {Boolean} autoPlay Is the audio autoplay, default value is false. 19 * @property {Boolean} loaded Is the audio resource loaded, readonly! 20 * @property {Boolean} playing Is the audio playing, readonly! 21 * @property {Number} duration The duration of the audio, readonly! 22 * @property {Number} volume The volume of the audio, value between 0 to 1. 23 * @property {Boolean} muted Is the audio muted, default value is false. 24 */ 25 var HTMLAudio = Class.create(/** @lends HTMLAudio.prototype */{ 26 Mixes: EventMixin, 27 constructor: function(properties){ 28 Hilo.copy(this, properties, true); 29 30 this._onAudioEvent = this._onAudioEvent.bind(this); 31 }, 32 33 src: null, 34 loop: false, 35 autoPlay: false, 36 loaded: false, 37 playing: false, 38 duration: 0, 39 volume: 1, 40 muted: false, 41 42 _element: null, //HTMLAudioElement对象 43 44 /** 45 * @language=en 46 * Load audio file. 47 */ 48 load: function(){ 49 if(!this._element){ 50 try{ 51 var elem = this._element = new Audio(); 52 elem.addEventListener('canplaythrough', this._onAudioEvent, false); 53 elem.addEventListener('ended', this._onAudioEvent, false); 54 elem.addEventListener('error', this._onAudioEvent, false); 55 elem.src = this.src; 56 elem.volume = this.volume; 57 elem.load(); 58 } 59 catch(err){ 60 //ie9 某些版本有Audio对象,但是执行play,pause会报错! 61 var elem = this._element = {}; 62 elem.play = elem.pause = function(){ 63 64 }; 65 } 66 } 67 return this; 68 }, 69 70 /** 71 * @language=en 72 * @private 73 */ 74 _onAudioEvent: function(e){ 75 // console.log('onAudioEvent:', e.type); 76 var type = e.type; 77 78 switch(type){ 79 case 'canplaythrough': 80 e.target.removeEventListener(type, this._onAudioEvent); 81 this.loaded = true; 82 this.duration = this._element.duration; 83 this.fire('load'); 84 if(this.autoPlay) this._doPlay(); 85 break; 86 case 'ended': 87 this.playing = false; 88 this.fire('end'); 89 if(this.loop) this._doPlay(); 90 break; 91 case 'error': 92 this.fire('error'); 93 break; 94 } 95 }, 96 97 /** 98 * @language=en 99 * @private 100 */ 101 _doPlay: function(){ 102 if(!this.playing){ 103 this._element.volume = this.muted ? 0 : this.volume; 104 this._element.play(); 105 this.playing = true; 106 } 107 }, 108 109 /** 110 * @language=en 111 * Start playing the audio. And play the audio from the beginning if the audio is already playing. 112 * Note: To prevent failing to play at the first time, play when the audio is loaded. 113 */ 114 play: function(){ 115 if(this.playing) this.stop(); 116 117 if(!this._element){ 118 this.autoPlay = true; 119 this.load(); 120 }else if(this.loaded){ 121 this._doPlay(); 122 } 123 124 return this; 125 }, 126 127 /** 128 * @language=en 129 * Pause (halt) the currently playing audio. 130 */ 131 pause: function(){ 132 if(this.playing){ 133 this._element.pause(); 134 this.playing = false; 135 } 136 return this; 137 }, 138 139 /** 140 * @language=en 141 * Continue to play the audio. 142 */ 143 resume: function(){ 144 if(!this.playing){ 145 this._doPlay(); 146 } 147 return this; 148 }, 149 150 /** 151 * @language=en 152 * Stop playing the audio. 153 */ 154 stop: function(){ 155 if(this.playing){ 156 this._element.pause(); 157 this._element.currentTime = 0; 158 this.playing = false; 159 } 160 return this; 161 }, 162 163 /** 164 * @language=en 165 * Set the volume. Note: iOS devices cannot set volume. 166 */ 167 setVolume: function(volume){ 168 if(this.volume != volume){ 169 this.volume = volume; 170 this._element.volume = volume; 171 } 172 return this; 173 }, 174 175 /** 176 * @language=en 177 * Set mute mode. Note: iOS devices cannot set mute mode. 178 */ 179 setMute: function(muted){ 180 if(this.muted != muted){ 181 this.muted = muted; 182 this._element.volume = muted ? 0 : this.volume; 183 } 184 return this; 185 }, 186 187 Statics: /** @lends HTMLAudio */ { 188 /** 189 * @language=en 190 * Does the browser supports HTMLAudio. 191 */ 192 isSupported: window.Audio !== null 193 } 194 195 });