use-sound
Version:
### A React Hook for Sound Effects
172 lines (142 loc) • 4.93 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
function _interopNamespace(e) {
if (e && e.__esModule) { return e; } else {
var n = {};
if (e) {
Object.keys(e).forEach(function (k) {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () {
return e[k];
}
});
});
}
n['default'] = e;
return n;
}
}
var React = require('react');
var React__default = _interopDefault(React);
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
function useOnMount(callback) {
React.useEffect(callback, []);
}
function useSound(url, _ref) {
if (_ref === void 0) {
_ref = {};
}
var _ref2 = _ref,
_ref2$volume = _ref2.volume,
volume = _ref2$volume === void 0 ? 1 : _ref2$volume,
_ref2$playbackRate = _ref2.playbackRate,
playbackRate = _ref2$playbackRate === void 0 ? 1 : _ref2$playbackRate,
_ref2$soundEnabled = _ref2.soundEnabled,
soundEnabled = _ref2$soundEnabled === void 0 ? true : _ref2$soundEnabled,
_ref2$interrupt = _ref2.interrupt,
interrupt = _ref2$interrupt === void 0 ? false : _ref2$interrupt,
delegated = _objectWithoutPropertiesLoose(_ref2, ["volume", "playbackRate", "soundEnabled", "interrupt"]);
var HowlConstructor = React__default.useRef(null);
var _React$useState = React__default.useState(false),
isPlaying = _React$useState[0],
setIsPlaying = _React$useState[1];
var _React$useState2 = React__default.useState(null),
sound = _React$useState2[0],
setSound = _React$useState2[1]; // We want to lazy-load Howler, since sounds can't play on load anyway.
useOnMount(function () {
new Promise(function (resolve) { resolve(_interopNamespace(require('howler'))); }).then(function (mod) {
HowlConstructor.current = mod.Howl;
var sound = new HowlConstructor.current(_extends({
src: [url],
volume: volume
}, delegated));
setSound(sound);
});
}); // When the URL changes, we have to do a whole thing where we recreate
// the Howl instance. This is because Howler doesn't expose a way to
// tweak the sound
React__default.useEffect(function () {
if (HowlConstructor.current && sound) {
setSound(new HowlConstructor.current(_extends({
src: [url],
volume: volume
}, delegated)));
} // The linter wants to run this effect whenever ANYTHING changes,
// but very specifically I only want to recreate the Howl instance
// when the `url` changes. Other changes should have no effect.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [url]); // Whenever volume/playbackRate are changed, change those properties
// on the sound instance.
React__default.useEffect(function () {
if (sound) {
sound.volume(volume);
sound.rate(playbackRate);
} // A weird bug means that including the `sound` here can trigger an
// error on unmount, where the state loses track of the sprites??
// No idea, but anyway I don't need to re-run this if only the `sound`
// changes.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [volume, playbackRate]);
var play = React__default.useCallback(function (options) {
if (options === void 0) {
options = {};
}
if (!sound || !soundEnabled && !options.forceSoundEnabled) {
return;
}
if (interrupt) {
sound.stop();
}
if (options.playbackRate) {
sound.rate(options.playbackRate);
}
sound.play(options.id);
sound.once('end', function () {
return setIsPlaying(false);
});
setIsPlaying(true);
}, [sound, soundEnabled, interrupt]);
var stop = React__default.useCallback(function () {
if (!sound) {
return;
}
sound.stop();
setIsPlaying(false);
}, [sound]);
var returnedValue = [play, {
sound: sound,
stop: stop,
isPlaying: isPlaying
}];
return returnedValue;
}
exports.default = useSound;
//# sourceMappingURL=use-sound.cjs.development.js.map