🎺 @vueuse/sound

A checkbox component with a twist! πŸ”Š
<template>  <div class="relative">    <input      type="checkbox"      @mousedown="active = true"      @mouseup="active = false"      @mouseout="active = false"      v-model="value"      class="absolute top-0 left-0 z-20 w-full h-full opacity-0 cursor-pointer"    />    <div class="relative z-10 flex items-center">      <div        class="relative flex items-center justify-center w-10 h-10 p-1 border-4 rounded-xl visible-box"        :style="{          transform: `scale(${outlineSpring.scale})`,        }"      >        <div          class="z-10 w-full h-full bg-pink-500 rounded-lg"          :style="{            transform: `scale(${filledSpring.scale})`,            opacity: `${filledSpring.scale}`,          }"        />      </div>    </div>  </div></template><script>import { useSound } from '@vueuse/sound'import { computed, reactive, ref, watch } from 'vue'import { spring } from 'vue3-spring'import popDown from '../assets/sounds/pop-down.mp3'import popUpOn from '../assets/sounds/pop-up-on.mp3'import popUpOff from '../assets/sounds/pop-up-off.mp3'export default {  model: {    prop: 'checked',    event: 'change',  },  emits: ['update:checked'],  props: {    checked: {      type: Boolean,      required: false,      default: false,    },  },  computed: {    value: {      get() {        return this.checked      },      set(value) {        if (this.value) {          this.filledSpring.scale = 1.0          this.onSound.play()        } else {          this.filledSpring.scale = 0          this.offSound.play()        }        this.$emit('update:checked', value)      },    },  },  setup({ checked }) {    // Sounds    const activeSound = useSound(popDown, { volume: 0.25 })    const onSound = useSound(popUpOn, { volume: 0.25 })    const offSound = useSound(popUpOff, { volume: 0.25 })    // Refs    const active = ref(false)    // Springs    const springConfig = {      stiffness: 400,      damping: 22,    }    const filledSpring = spring({ scale: 1.0 }, springConfig)    const outlineSpring = spring(      {        scale: 1.0,      },      springConfig,    )    // Watchers    watch([active], () => {      if (active.value) {        activeSound.play()        outlineSpring.scale = 0.8      } else {        outlineSpring.scale = 1      }    })    return {      active,      activeSound,      onSound,      offSound,      filledSpring,      outlineSpring,    }  },}</script>
Play a sound when hovering the trumpet.
<template>  <div class="flex justify-center">    <Button @mouseover="play" @mouseleave="stop" label="Trumpet"> 🎺 </Button>  </div></template><script>import { useSound } from '@vueuse/sound'import trumpetSfx from '../assets/sounds/fanfare.mp3'import Button from './Button.vue'export default {  components: {    Button  },  setup() {    const { play, stop } = useSound(trumpetSfx)    return {      play,      stop,    }  },}</script>
Increase pitch each time we click the button.
<template>  <div class="flex justify-center">    <Button @click="handleClick" label="Person with lines from mouth">πŸ—£</Button>  </div></template><script>import { ref } from 'vue'import { useSound } from '@vueuse/sound'import glugSfx from '../assets/sounds/glug.mp3'import Button from './Button.vue'export default {  components: { Button },  setup() {    const playbackRate = ref(0.75)    const { play } = useSound(glugSfx, {      playbackRate,      interrupt: true,    })    const handleClick = () => {      playbackRate.value = playbackRate.value + 0.1      play()    }    return {      handleClick    }  },}</script>
A drum basic yet fun drum machine, showing how to use sound sprites.
You can also use keyboard keys to play the drum machine: 1️⃣ , 2️⃣ , 3️⃣ , 4️⃣
<template>    <div class="flex items-center justify-center gap-4">      <Button @click="play({ id: 'kick' })" label="Kick">πŸ₯</Button>      <Button @click="play({ id: 'hihat' })" label="Hi-hat">🎩</Button>      <Button @click="play({ id: 'snare' })" label="Snare">πŸ—</Button>      <Button @click="play({ id: 'cowbell' })" label="Cowbell">πŸ””</Button>    </div></template><script>import { onMounted, onUnmounted } from 'vue'import { useSound } from '@vueuse/sound'import drumSfx from '../assets/sounds/909-drums.mp3'import Button from './Button.vue'const useKeyboardBindings = (map) => {  const handlePress = (ev) => {    const handler = map[ev.key]    if (typeof handler === 'function') {      handler()    }  }  onMounted(() => {    window.addEventListener('keydown', handlePress)  })  onUnmounted(() => {    window.removeEventListener('keydown', handlePress)  })}export default {  components: { Button },  setup() {    const { play } = useSound(drumSfx, {      sprite: {        kick: [0, 350],        hihat: [374, 160],        snare: [666, 290],        cowbell: [968, 200],      },    })    useKeyboardBindings({      1: () => play({ id: 'kick' }),      2: () => play({ id: 'hihat' }),      3: () => play({ id: 'snare' }),      4: () => play({ id: 'cowbell' }),    })    return {      play,    }  },}</script>
Play the sound with a random volume value.
<template>  <div class="flex flex-col justify-center">    <div class="flex justify-center mb-6">      <Button @click="handleClick" label="Control knobs">πŸŽ›οΈ</Button>    </div>  </div></template><script>import { ref } from 'vue'import { useSound } from '@vueuse/sound'import glugSfx from '../assets/sounds/glug.mp3'import Button from './Button.vue'export default {  components: { Button },  setup() {    const volume = ref(0.1)    const { play } = useSound(glugSfx, {      volume,      interrupt: true,    })    const handleClick = () => {      volume.value = parseFloat(Math.random().toFixed(2))      play()    }    return {      handleClick    }  },}</script>