react-howler
Version:
A React.js wrapper for howler.js (audio player)
380 lines (315 loc) • 10.8 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _howler4 = require('./howler');
var _utils = require('./utils');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var ReactHowler = function (_Component) {
_inherits(ReactHowler, _Component);
function ReactHowler(props) {
_classCallCheck(this, ReactHowler);
var _this = _possibleConstructorReturn(this, (ReactHowler.__proto__ || Object.getPrototypeOf(ReactHowler)).call(this, props));
_this.initHowler = _this.initHowler.bind(_this);
return _this;
}
_createClass(ReactHowler, [{
key: 'componentDidMount',
value: function componentDidMount() {
this.initHowler();
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate(prevProps) {
// The src prop must be either a string or an array of strings
// Because of this, we can use it's JSON representation to check for changes
if (JSON.stringify(prevProps.src) !== JSON.stringify(this.props.src)) {
this.initHowler(this.props);
} else {
this.toggleHowler(prevProps);
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.destroyHowler();
}
/**
* Create howler object with given props
*/
}, {
key: 'initHowler',
value: function initHowler() {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props;
this.destroyHowler();
if (typeof _howler4.Howl !== 'undefined') {
// Check if window is available
this.howler = new _howler4.Howl({
src: props.src,
xhr: props.xhr,
format: props.format,
mute: props.mute,
loop: props.loop,
preload: props.preload,
volume: props.volume,
rate: props.rate,
onend: props.onEnd,
onplay: props.onPlay,
onplayerror: props.onPlayError,
onpause: props.onPause,
onvolume: props.onVolume,
onstop: props.onStop,
onload: props.onLoad,
onseek: props.onSeek,
onloaderror: props.onLoadError,
html5: props.html5
});
if (props.playing) {
this.play();
}
}
}
/**
* Stop, unload and destroy howler object
*/
}, {
key: 'destroyHowler',
value: function destroyHowler() {
if (this.howler) {
this.howler.off(); // Remove event listener
this.howler.stop(); // Stop playback
this.howler.unload(); // Remove sound from pool
this.howler = null; // Destroy it
}
}
}, {
key: 'toggleHowler',
value: function toggleHowler(prevProps) {
this.props.playing ? this.play() : this.pause();
this.loop(this.props.loop);
if (prevProps.mute !== this.props.mute) {
this.mute(this.props.mute);
}
if (prevProps.volume !== this.props.volume) {
this.volume(this.props.volume);
}
if (this.props.preload && this.howlerState() === 'unloaded') {
this.load();
}
}
}, {
key: 'play',
/**
* Begins playback of a sound when not playing
*/
value: function play() {
var playing = this.howler.playing();
if (!playing) {
// Automatically load if we're trying to play
// and the howl is not loaded
if (this.howlerState() === 'unloaded') {
this.load();
}
this.howler.play();
}
}
/**
* Pauses playback of sound or group
* If no id given, pauses all playback
* @param {Number} id = undefined [sound of group to pause]
*/
}, {
key: 'pause',
value: function pause() {
var id = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
if (id) {
this.howler.pause(id);
} else {
this.howler.pause();
}
}
/**
* Update playback rate (speed) of sound or group
* If no value given, apply default rate of 1
* If no id given, apply rate to all
* @param {Number} value = 1 [rate to apply]
* @param {Number} id = undefined [sound of group to update]
*/
}, {
key: 'rate',
value: function rate() {
var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
if (typeof value === 'number') {
if (id) {
this.howler.rate(value, id);
} else {
this.howler.rate(value);
}
}
}
/**
* Check the load status of the Howl
* @return {String} [unloaded, loading or loaded]
*/
}, {
key: 'howlerState',
value: function howlerState() {
return this.howler.state();
}
/**
* Stops playback of sound or group
* If no id given, stops all playback
* @param {Number} id = undefined [sound of group to pause]
*/
}, {
key: 'stop',
value: function stop() {
var id = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
if (id) {
this.howler.stop(id);
} else {
this.howler.stop();
}
}
/**
* Mutes the sound, but doesn't pause the playback.
* @param {Boolean} [muted] [True to mute and false to unmute]
* @param {Number} [id] [The sound ID. If none is passed, all sounds in group are muted]
*/
}, {
key: 'mute',
value: function mute() {
var _howler;
(_howler = this.howler).mute.apply(_howler, arguments);
}
/**
* Get/set volume of this sound or the group. This method optionally takes 0, 1 or 2 arguments.
* @param {Number} [volume] [Volume from 0.0 to 1.0]
* @param {Number} [id] [The sound ID. If none is passed, all sounds in group are muted]
*/
}, {
key: 'volume',
value: function volume() {
var _howler2;
return (_howler2 = this.howler).volume.apply(_howler2, arguments);
}
/**
* Get/set whether to loop the sound or group. This method can optionally take 0, 1 or 2 arguments.
* @param {Boolean} [loop] [To loop or not to loop, that is the question]
* @param {Number} [id] [The sound ID. If none is passed, all sounds in group will have their loop property updated]
*/
}, {
key: 'loop',
value: function loop() {
var _howler3;
return (_howler3 = this.howler).loop.apply(_howler3, arguments);
}
/**
* Set/get current position of player
* @param {Number} pos [seek player to position]
* @return {Number} [return current position]
*/
}, {
key: 'seek',
value: function seek() {
var pos = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
if (!this.howler) {
return 0;
}
if (!pos && pos !== 0) {
return this.howler.seek();
}
if (pos || pos === 0) {
this.howler.seek(pos);
return pos;
}
}
/**
* Get the duration of the audio source
* @return {Number} [Audio length in seconds. Will return 0 until after the load event fires]
*/
}, {
key: 'duration',
value: function duration() {
return this.howler.duration();
}
/**
* load audio file
*/
}, {
key: 'load',
value: function load() {
this.howler.load();
}
/**
* Only render a placeholder
*/
}, {
key: 'render',
value: function render() {
return _react2.default.createElement('div', null);
}
}, {
key: 'howler',
set: function set(howl) {
if (howl) {
this._howler = howl;
}
},
get: function get() {
return this._howler;
}
}]);
return ReactHowler;
}(_react.Component);
ReactHowler.propTypes = {
src: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.arrayOf(_propTypes2.default.string)]).isRequired,
format: _propTypes2.default.arrayOf(_propTypes2.default.string),
xhr: _propTypes2.default.object,
playing: _propTypes2.default.bool,
mute: _propTypes2.default.bool,
loop: _propTypes2.default.bool,
preload: _propTypes2.default.bool,
volume: _propTypes2.default.number,
rate: _propTypes2.default.number,
onEnd: _propTypes2.default.func,
onPause: _propTypes2.default.func,
onPlay: _propTypes2.default.func,
onPlayError: _propTypes2.default.func,
onVolume: _propTypes2.default.func,
onStop: _propTypes2.default.func,
onLoad: _propTypes2.default.func,
onSeek: _propTypes2.default.func,
onLoadError: _propTypes2.default.func,
html5: _propTypes2.default.bool
};
ReactHowler.defaultProps = {
playing: true, // Enable autoplay by default
format: [],
xhr: {},
mute: false,
preload: true,
loop: false,
volume: 1.0,
rate: 1,
onEnd: _utils.noop,
onPause: _utils.noop,
onPlay: _utils.noop,
onPlayError: _utils.noop,
onVolume: _utils.noop,
onStop: _utils.noop,
onLoad: _utils.noop,
onSeek: _utils.noop,
onLoadError: _utils.noop,
html5: false
};
exports.default = ReactHowler;