Skip to content

Commit

Permalink
Merge PR #321 | Setup Howler.js
Browse files Browse the repository at this point in the history
from mateusfg7/setup-howler.js
  • Loading branch information
mateusfg7 authored Jul 14, 2022
2 parents 22c5e27 + f9e53b1 commit 0f0b7b6
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 29 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
],
"rules": {
"prettier/prettier": "error",
"no-unused-vars": "warn",
"no-use-before-define": "off",
"react/react-in-jsx-scope": "off",
"react/prop-types": "off",
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"@fortawesome/fontawesome-svg-core": "6.1.1",
"@fortawesome/free-solid-svg-icons": "6.1.1",
"@fortawesome/react-fontawesome": "0.2.0",
"howler": "^2.2.3",
"next": "12.2.2",
"next-pwa": "5.5.4",
"react": "18.2.0",
Expand All @@ -24,6 +25,7 @@
"@commitlint/cli": "17.0.3",
"@commitlint/config-conventional": "17.0.3",
"@next/eslint-plugin-next": "12.2.2",
"@types/howler": "^2.2.7",
"@types/react": "18.0.15",
"@types/styled-components": "5.1.25",
"@typescript-eslint/eslint-plugin": "5.30.5",
Expand Down
58 changes: 43 additions & 15 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,38 +15,64 @@ 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)
const [currentSoundVolume, setCurrentSoundVolume] = useState(1)

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

function toggleSoundState() {
const soundHTMLElement = soundHTMLRef.current
async function toggleSoundState() {
if (howlSoundInstance) {
if (soundIsActive) {
howlSoundInstance.fade(currentSoundVolume, 0, FADE_TIME_MS)
await sleep(FADE_TIME_MS)
howlSoundInstance.pause()
} else {
howlSoundInstance.fade(0, currentSoundVolume, FADE_TIME_MS)
howlSoundInstance.play()
}

if (!soundIsActive) soundHTMLElement.play()
else soundHTMLElement.pause()
setSoundIsActive(!soundIsActive)
}
}

setSoundIsActive(!soundIsActive)
function handleSoundVolume(volume: number) {
if (howlSoundInstance) {
howlSoundInstance.volume(volume)
setCurrentSoundVolume(volume)
}
}

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
state={soundIsActive}
audioElement={soundHTMLRef.current}
handleSoundVolume={handleSoundVolume}
/>
</SoundComponent>
)
Expand Down
30 changes: 23 additions & 7 deletions src/components/Sound/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ export const SoundButton = styled.div`
transition: 0.3s;
img {
border: 1px solid red;
filter: invert(100%) sepia(100%) saturate(0%) hue-rotate(288deg)
brightness(102%) contrast(102%);
opacity: 0.7;
}
cursor: pointer;
&.selected {
color: rgba(255, 255, 255, 1);
img {
Expand All @@ -32,14 +41,13 @@ export const SoundButton = styled.div`
border-radius: 10% 10% 0 0;
}
img {
border: 1px solid red;
filter: invert(100%) sepia(100%) saturate(0%) hue-rotate(288deg)
brightness(102%) contrast(102%);
opacity: 0.7;
}
&.disabled {
cursor: not-allowed;
cursor: pointer;
img {
opacity: 0.2;
}
}
@media (min-width: 700px) {
&.selected {
Expand All @@ -60,5 +68,13 @@ export const SoundButton = styled.div`
box-shadow: 0px 0px 30px rgba(0, 0, 0, 0.05);
background: rgba(255, 255, 255, 0.1);
}
&.disabled:hover {
box-shadow: none;
img {
opacity: 0.2;
}
background: none;
}
}
`
10 changes: 3 additions & 7 deletions src/components/VolumeController/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,15 @@ import VolumeControllerInput from './styles'

export interface IVolumeController {
state: boolean
audioElement: HTMLAudioElement
handleSoundVolume: (volume: number) => void
}

export const VolumeController: React.FC<IVolumeController> = ({
state,
audioElement
handleSoundVolume
}) => {
const [rangeValue, setRangeValue] = useState(1000)

function handleVolume(volume: number) {
audioElement.volume = volume
}

return (
<VolumeControllerInput
className={state ? 'selected' : ''}
Expand All @@ -28,7 +24,7 @@ export const VolumeController: React.FC<IVolumeController> = ({
percentValue={(rangeValue * 100) / 1000}
onChange={event => {
setRangeValue(Number(event.target.value))
handleVolume(Number(event.target.value) / 1000)
handleSoundVolume(Number(event.target.value) / 1000)
}}
/>
)
Expand Down

1 comment on commit 0f0b7b6

@vercel
Copy link

@vercel vercel bot commented on 0f0b7b6 Jul 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

noisekun – ./

noisekun-mateusfg7.vercel.app
noisekun-git-main-mateusfg7.vercel.app
noisekun.vercel.app

Please sign in to comment.