Skip to content

Commit

Permalink
feat(howler.js): set initial use of howler.js
Browse files Browse the repository at this point in the history
Changes on `Sound` component
* Set howler instance with `useEffect` and `useState`
* Define "sound is loading" state for unloaded sounds
* Add fade-in/fade-out on sound volume for play/pause action
  • Loading branch information
mateusfg7 committed Jul 14, 2022
1 parent 11c7677 commit be200da
Showing 1 changed file with 36 additions and 16 deletions.
52 changes: 36 additions & 16 deletions src/components/Sound/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React, { useRef, useState } from 'react'
/* eslint-disable multiline-ternary */
import React, { useEffect, useState } from 'react'
import Image from 'next/image'
import { Howl, Howler } from 'howler'

import { VolumeController } from '../VolumeController'
import { SoundComponent, SoundButton } from './styles'
Expand All @@ -13,39 +15,57 @@ export interface ISound {
}
}

const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))

export const Sound: React.FC<ISound> = ({ name, iconFile, audioFile }) => {
const FADE_TIME_MS = 500

const [soundIsActive, setSoundIsActive] = useState(false)
const soundHTMLRef = useRef<HTMLAudioElement>()
const [howlSoundInstance, setHowlSoundInstance] = useState<Howl | null>(null)
const [soundIsLoading, setSoundIsLoading] = useState(true)

function toggleSoundState() {
const soundHTMLElement = soundHTMLRef.current
useEffect(() => {
setHowlSoundInstance(
new Howl({
src: `./sounds/${audioFile.name}`,
loop: true,
onload: () => {
setSoundIsLoading(false)
}
})
)
}, [])

if (!soundIsActive) soundHTMLElement.play()
else soundHTMLElement.pause()
async function toggleSoundState() {
if (howlSoundInstance) {
if (soundIsActive) {
howlSoundInstance.fade(1, 0, FADE_TIME_MS)
await sleep(FADE_TIME_MS)
howlSoundInstance.pause()
} else {
howlSoundInstance.fade(0, 1, FADE_TIME_MS)
howlSoundInstance.play()
}

setSoundIsActive(!soundIsActive)
setSoundIsActive(!soundIsActive)
}
}

return (
<SoundComponent title={name}>
<audio loop preload="true" ref={soundHTMLRef}>
<source src={`/sounds/${audioFile.name}`} type={audioFile.type} />
</audio>

<SoundButton
id={`${name}-button`}
className={`${
soundIsActive ? 'selected' : ''
className={`${soundIsActive ? 'selected' : ''} ${
soundIsLoading && 'disabled'
} umami--click--${name}-sound`}
onClick={() => toggleSoundState()}
>
<Image src={`/assets/${iconFile}`} alt={name} width={80} height={80} />
</SoundButton>

<VolumeController
{/* <VolumeController
state={soundIsActive}
audioElement={soundHTMLRef.current}
/>
/> */}
</SoundComponent>
)
}

0 comments on commit be200da

Please sign in to comment.