Spice Up Your Svelte App with Sound Interactions using svelte-sound 😎
Tags: svelte, javascript, typescript, opensource
Published: 2023-03-20 19:34:21


How many of you have wondered how games are so addictive? One of the top reasons for that is the sound interactions they provide. 🎮

When we think of human senses, we think of eyesight, hearing, taste, touch and smell. As web developers, we develop our sites and apps for eyesight and touch (mobile devices), but we can’t do much with smell and taste. 😢 But what about hearing? It’s achievable and it’s done on many places. 🙌

One such example of audio/sound interactions is [Josh W Comeau](https://www.joshwcomeau.com/)’s site (even he has dedicated a post for it [here](https://www.joshwcomeau.com/react/announcing-use-sound-react-hook/)). His site is full of delightful sounds that make you want to explore more. 🤩

After wondering about this for a while, I did some research and started digging deep into it and finally ended up creating [`svelte-sound`](https://github.com/Rajaniraiyn/svelte-sound). 🚀

`svelte-sound` is a library that provides svelte actions to play interaction sounds on target DOM events. It uses [Howler.js](https://howlerjs.com/) under the hood for cross-browser compatibility and performance. 💯 It also supports dynamic imports and tree-shaking for advanced optimizations. 🌳

In this post, I will show you how to install and use `svelte-sound` in your svelte projects. I will also explain how it works internally using Svelte Action and Howler.js. 🧐

Are you ready to make your svelte app more engaging and fun? 😎 Let’s get started! 👇

## What is svelte-sound?

Svelte-sound is a svelte action library that lets you play interaction sounds on target DOM events with ease and flexibility. It has the following features:

- **Lightweight and performant**: It uses only the core of [howler.js](https://howlerjs.com/), a popular JavaScript audio library for the modern web. Howler.js handles all the edge cases and bugs across browsers and platforms, supports all codecs for full cross-browser compatibility, and caches sounds for better performance.
- **First in class TypeScript support**: It comes with TypeScript definitions out of the box, so you can enjoy type checking and auto-completion in your IDE.
- **Dynamic imports**: It loads howler.js using dynamic imports to support partial hydration. This means that howler.js will only be loaded when it's needed, saving bandwidth and improving loading time.
- **Scalable**: It can be used for simple sound effects or complex game interactions. You can control everything from play, pause and seek to rate, fade and loop, just to name a few.
- **Truly reactive by default**: It leverages Svelte's reactivity system to update sounds automatically when their props change. You don't need to worry about managing state or lifecycle methods.

With svelte-sound, you can add sound interactions to your Svelte app with just a few lines of code. Let's see how it works. 🔊

## Getting Started

Its straight forward to start using `svelte-sound` in your svelte projects.

### Installation

You can install svelte-sound using your preferred package manager. For example:

```bash
npm install svelte-sound
```
or
```bash
yarn add svelte-sound
```
or
```bash
pnpm install svelte-sound
```

### Usage

we can use `svelte-sound` in following ways,
- The `sound` action directly on an element, or
- The `useSound` reusable action builder that returns a svelte action.

## Let’s see how each of them works.👇

### `sound` action

The `sound` action can be directly used on elements within svelte as a svelte action. You need to import it from `"svelte-sound"` and pass an object with two properties: `src` and `events`. The `src` is the URL of the sound file you want to play, and the `events` is an array of DOM events that will trigger the sound.

| Property | Type | Description |
| :--: | :--: | :-- |
| `src` | `string` | url of the audio file to be used as an audio source |
| `events` | `string[]` | any valid javascript events as array of string |

**Note:** Additionally the option can take any valid [_Howler.js Core Options_](https://github.com/goldfire/howler.js#core)

For example:
```html
<script>
import { sound } from “svelte-sound”;
import click_mp4 from “./assets/click.mp4”;
</script>

<button use:sound={{ src: click_mp4, events: [“click”]}}> Click Me!! 🔊 
</button >
```

In this example, we are using a local sound file called _"click.mp4"_ that will play when we click on the button. You can also use online sound files by passing their URLs as strings. For example:
```html
<script>
import { sound } from “svelte-sound”;
</ script >

<button use:sound={{ 
src: “https://example.com/sounds/click.mp4”,
events: [“click”]
}}> 
Click Me!! 🔊 
</button>
```
You can also specify multiple events for the same sound file by adding them to the array. For example:
```html
<script>
import { sound } from “svelte-sound”;
import hover_mp4 from “./assets/hover.mp4”;
</script>

<button use:sound={{
src: hover_mp4,
events: [“mouseover”, “mouseout”]
}}> 
Hover Me!! 🎶 
</button>
```
In this example, we are using a local sound file called _"hover.mp4"_ that will play when we hover over or out of the button.


### `useSound` action builder

The `useSound` function can be reused multiple times on multiple elements within svelte. It returns a svelte action that you can apply to any element, which is re-useable and overridable.

`useSound`'s API is very similar to that of `sound` but it takes three parameters

| Parameter | Type | Description |
| :--: | :--: | :-- |
| `src`<sup>*</sup> | `string` | URL of the audio file to load as string |
| `events`<sup>*</sup> | `string[]` | any valid javascript events as array of string |
| `options` | [`HowlOptions`](https://github.com/lionelB/DefinitelyTyped/blob/fa1c22c1edb4a3bba3cb9c2e2e16f2b44ba95936/types/howler/index.d.ts#L85) | Howler.js options to be passed into the Howler constructor |
**Note:** * are required parameters


You need to import it from `"svelte-sound"` and pass two arguments: the URL of the sound file (either local or online) and an array of DOM events that will trigger the sound. For example:
```html
<script>
import { useSound } from “svelte-sound”;
import click_mp4 from “./assets/click.mp4”;
const click_sound = useSound(click_mp4, [“click”])
</script>

<button use:click_sound> Click Me!! 🔊 </ button >
```

In this example, we are creating a reusable action called `click_sound` that will play a local sound file called _"click.mp4"_ when we click on any element that uses it.

You can also overwrite the options for each element by passing an object with new properties. For example:
```html
<script>
import { useSound } from “svelte-sound”;
import click_mp4 from “./assets/click.mp4”;
const click_sound = useSound(click_mp4, [“click”])
</script>

<button use:click_sound> Click Me!! 🔊 </button>
<!-- Options can be overwritten -->
<button use:click_sound= {{ events: [“dblclick”]}}>
Double Click Me!! 🎵🎵
</ button >
```
In this example, we are changing the event for one of the buttons to `"dblclick"` instead of `"click"`.


### Play below with the code ↓↓↓
{% embed https://stackblitz.com/edit/vitejs-vite-vc33jx?file=src/lib/Counter.svelte %}


## Internals

> ⚠️ Beware of too much of technical jargon below

This package uses [Svelte Action](https://svelte.dev/docs#template-syntax-element-directives-use-action) to play sounds on DOM events with [Howler.js](https://howlerjs.com/).

I built this library in a way that it uses dynamic imports and tree-shaking for advanced optimizations. Thus ensures very lightweight (_less than **`1kb`**_) and more performant (using [Howler.js](https://howlerjs.com/))

### Svelte Action

A Svelte Action is a function that can be applied to any element using the `use` directive. It receives a node and some parameters, and returns an object with a `destroy` function.

### _Howler.js_ in `svelte-sound`

[Howler.js](https://howlerjs.com/) is a JavaScript audio library that supports multiple file formats, cross-browser compatibility, spatial sound effects, fading, looping, caching and more.

`svelte-sound` uses Howler.js under the hood to play sound files on target DOM events. It loads Howler.js using dynamic imports to support partial hydration. It also uses only Howler core module which has all the essential features without any extra plugins.

## How svelte-sound creates actions?

`svelte-sound` exports two functions: `sound` and `useSound`. Both of them are Svelte Actions that use Howler.js internally.

## Conclusion

In this post, I showed you how to use svelte-sound, a library that I created to add sound effects to your svelte app. We also explored how it works internally using Svelte Action and Howler.js.

As [Josh W Comeau](https://www.joshwcomeau.com), the original inspiration for this package, said: 
> ### A million possibilities
> The thing that strikes me about using audio on the web is that there is so much under-explored territory. I've been experimenting with sound for a while now, and I still feel like I'm just scratching the surface.
> You've been given the tools to start experimenting, and I'd encourage you to have some fun with this, and see where it takes you =)

I hope you enjoyed this post and found it useful. If you have any questions or feedback, please let me know in the comments below.😊

And if you liked `svelte-sound`, please consider giving it a star on [GitHub](https://github.com/Rajaniraiyn/svelte-sound). It would mean a lot to me.🙏