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