Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

🔊 A Vue composable for playing sound effects

License

NotificationsYou must be signed in to change notification settings

vueuse/sound

Repository files navigation

npmnpmNetlify Status

  • 👂 Lets your websitecommunicate using 2human senses instead of 1
  • 🔥 Built withVue Composition API
  • ✅ SupportsVue 2 & 3 usingvue-demi
  • 🚚 SupportsNuxt 2 & 3 using@vueuse/sound/nuxt
  • ⚡️<1kb bytes (gzip) in yourbundle!~10kb loadedasync.
  • ✨ Built withTypeScript
  • 🗣 Uses a powerful, battle-tested audio utility:Howler.js

If you want to take aquick look at the composable in effect, you should visit the🌍demo.

This package is aVue version of theuseSound React hook byjoshwcomeau.

Installation

Package can be added usingyarn:

yarn add @vueuse/sound

Or, use NPM:

npm install @vueuse/sound

Examples

Play a sound on click

This is the most basic example of how fast you can implement sounds in your app using @vueuse/sound.

<template><button @click="play">Play a sound</button></template><script>import{ useSound}from'@vueuse/sound'importbuttonSfxfrom'../assets/sounds/button.mp3'exportdefault{setup(){const{ play}=useSound(buttonSfx)return{      play,}},}</script>

Playing on hover

This example is shown in thedemo.

Increase pitch on every click

This example is shown in thedemo.

Usage Notes

No sounds immediately after load

For the user's sake, browsers don't allow websites to produce sound until the user has interacted with them (eg. by clicking on something). No sound will be produced until the user clicks, taps, or triggers something.

useSound takes advantage of this: because we know that sounds won't be needed immediately on-load, we can lazy-load a third-party dependency.

useSound will add about 1kb gzip to your bundle, and will asynchronously fetch an additional package after load, which clocks in around 9kb gzip.

If the user does happen to click with something that makes noise before this dependency has been loaded and fetched, it will be a no-op (everything will still work, but no sound effect will play). In my experience this is exceedingly rare.

Reactive configuration

Consider the following snippet of code:

constplaybackRate=ref(0.75)const{ play}=useSound('/path/to/sound',{ playbackRate})

playbackRate doesn't just serve as aninitial value for the sound effect. IfplaybackRate changes, the sound will immediately begin playing at a new rate. This is true for all options passed to theuseSound composable.

API Documentation

TheuseSound composable takes two arguments:

  • A URL to the sound that it wil load
  • A config object (ComposableOptions)

It produces an array with two values:

  • A function you can call to trigger the sound
  • An object with additional data and controls (ExposedData)

When calling the function to play the sound, you can pass it a set of options (PlayOptions).

Let's go through each of these in turn.

ComposableOptions

When callinguseSound, you can pass it a variety of options:

NameValue
volumenumber
playbackRatenumber
interruptboolean
soundEnabledboolean
spriteSpriteMap
[delegated]
  • volume is a number from0 to1, where1 is full volume and0 is comletely muted.
  • playbackRate is a number from0.5 to4. It can be used to slow down or speed up the sample. Like a turntable, changes to speed also affect pitch.
  • interrupt specifies whether or not the sound should be able to "overlap" if theplay function is called again before the sound has ended.
  • soundEnabled allows you to pass a value (typically from context or redux or something) to mute all sounds. Note that this can be overridden in thePlayOptions, see below
  • sprite allows you to use a singleuseSound composable for multiple sound effects. See“Sprites” below.

[delegated] refers to the fact that any additional argument you pass inComposableOptions will be forwarded to theHowl constructor. See "Escape hatches" below for more information.

Theplay function

When calling the composable, you get back a play function as the first item in the tuple:

const{ play}=useSound('/meow.mp3')//      ^ What we're talking about

You can call this function without any arguments when you want to trigger the sound. You can also call it with aPlayOptions object:

NameValue
idstring
forceSoundEnabledboolean
playbackRatenumber
  • id is used for sprite identification. See“Sprites” below.
  • forceSoundEnabled allows you to override thesoundEnabled boolean passed toComposableOptions. You generally never want to do this. The only exception I've found: triggering a sound on the "Mute" button.
  • playbackRate is another way you can set a new playback rate, same as inComposableOptions. In general you should prefer to do it throughComposableOptions, this is an escape hatch.

ExposedData

The composable produces a tuple with 2 options, the play function and anExposedData object:

const[play,exposedData]=useSound('/meow.mp3')//                ^ What we're talking about
NameValue
stopfunction ((id?: string) => void)
pausefunction ((id?: string) => void)
isPlayingboolean
durationnumber (or null)
soundHowl (or null)
  • stop is a function you can use to pre-emptively halt the sound.
  • pause is likestop, except it can be resumed from the same point. Unless you know you'll want to resume, you should usestop;pause hogs resources, since it expects to be resumed at some point.
  • isPlaying lets you know whether this sound is currently playing or not. When the sound reaches the end, or it's interrupted withstop orpaused, this value will flip back tofalse. You can use this to show some UI only while the sound is playing.
  • duration is the length of the sample, in milliseconds. It will benull until the sample has been loaded. Note that for sprites, it's the length of the entire file.
  • sound is an escape hatch. It grants you access to the underlyingHowl instance. See theHowler documentation to learn more about how to use it. Note that this will benull for the first few moments after the component mounts.

Advanced

Sprites

An audio sprite is a single audio file that holds multiple samples. Instead of loading many individual sounds, you can load a single file and slice it up into multiple sections which can be triggered independently.

There can be a performance benefit to this, since it's less parallel network requests, but it can also be worth doing this if a single component needs multiple samples. See theDrum Machine component for an example.

For sprites, we'll need to define aSpriteMap. It looks like this:

constspriteMap={laser:[0,300],explosion:[1000,300],meow:[2000,75],}

SpriteMap is an object. The keys are theids for individual sounds. The value is a tuple (array of fixed length) with 2 items:

  • The starting time of the sample, in milliseconds, counted from the very beginning of the sample
  • The length of the sample, in milliseconds.

This visualization might make it clearer:

Waveform visualization showing how each sprite occupies a chunk of time, and is labeled by its start time and duration

We can pass our SpriteMap as one of our ComposableOptions:

const{ play}=useSound('/path/to/sprite.mp3',{sprite:{laser:[0,300],explosion:[1000,300],meow:[2000,75],},})

To play a specific sprite, we'll pass itsid when calling theplay function:

<button  @click="play({id: 'laser'})">

Escape hatches

Howler is a very powerful library, and we've only exposed a tiny slice of what it can do inuseSound. We expose two escape hatches to give you more control.

First, any unrecognized option you pass toComposableOptions will be delegated toHowl. You can see thefull list of options in the Howler docs. Here's an example of how we can useonend to fire a function when our sound stops playing:

const{ play}=useSound('/thing.mp3',{onend:()=>{console.info('Sound ended!')},})

If you need more control, you should be able to use thesound object directly, which is an instance of Howler.

For example: Howlerexposes afade method, which lets you fade a sound in or out. You can call this method directly on thesound object:

<template><button      @click={sound.fade(0,1,1000)}>      Click to win</button></template><script>import{ useSound}from'@vueuse/sound'exportdefault{setup(){const{ play, sound}=useSound('/win-theme.mp3')return{            sound}}}</script>

Vite

If you are using Vite, you should add the following to your defineConfig options in vite.config.js:

optimizeDeps:{exclude:['vue-demi']}

Nuxt

If you use Nuxt 2, you must have@nuxt/bridge setup in your project.

Once you installed it, add@vueuse/sound/nuxt dependency to your project.

Add@vueuse/sound/nuxt to themodules section of yournuxt.config:

defineNuxtConfig({modules:['@vueuse/sound/nuxt']})

Configure your sounds 🥁:

defineNuxtConfig({sound:{sounds:{back:{src:"/back.wav",options:{volume:0.25}}}}})

You can also automatically scan an generate typings for your sounds inpublic/sounds directory by usingscan feature:

defineNuxtConfig({sound:{sounds:{scan:true}}})

Then move your sounds intopublic/sounds directory, and get autocompletion onuseSound({url}).

Credits

All thecredit behind thisidea goes toJosh W. Comeau.

Thedocumentation of this package has only been updated forVue Composition API instead ofReact Hooks.

If youlike this package, considerfollowing me onGitHub and onTwitter.


[8]ページ先頭

©2009-2025 Movatter.jp