Skip to content

Commit

Permalink
feat: implement non-linear volume slider
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffreyCA committed Jan 11, 2021
1 parent ee5cff4 commit a7b9cec
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 11 deletions.
42 changes: 42 additions & 0 deletions __tests__/tests/player.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1689,4 +1689,46 @@ describe('<ReactJkMusicPlayer/>', () => {
expect(audio.volume).toStrictEqual(0.5)
expect(fn).toHaveBeenCalledTimes(1)
})

it('should set audio volume non-linearly', async () => {
const wrapper = mount(
<ReactJkMusicPlayer
audioLists={[
{ musicSrc: 'x', cover: '' },
{ musicSrc: 'xx', cover: '' },
]}
mode="full"
/>,
)
expect(wrapper.state('currentAudioVolume')).toStrictEqual(1)
expect(wrapper.instance().audio.volume).toStrictEqual(1)

wrapper.instance().setAudioVolume(0.5)

expect(wrapper.state('currentAudioVolume')).toStrictEqual(0.5)
expect(wrapper.instance().audio.volume).toStrictEqual(0.25)
})

it('should set volume slider value non-linearly and invoke onAudioVolumeChange', async () => {
const fn = jest.fn()
const wrapper = mount(
<ReactJkMusicPlayer
audioLists={[
{ musicSrc: 'x', cover: '' },
{ musicSrc: 'xx', cover: '' },
]}
mode="full"
onAudioVolumeChange={fn}
/>,
)
expect(wrapper.state('soundValue')).toStrictEqual(1)
expect(wrapper.instance().audio.volume).toStrictEqual(1)

wrapper.instance().audio.volume = 0.25
wrapper.instance().onAudioVolumeChange()

expect(fn).toHaveBeenCalledWith(0.25)
expect(wrapper.instance().audio.volume).toStrictEqual(0.25)
expect(wrapper.state('soundValue')).toStrictEqual(0.5)
})
})
30 changes: 19 additions & 11 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1042,17 +1042,17 @@ export default class ReactJkMusicPlayer extends PureComponent {
this.setAudioVolume(currentAudioVolume || 0.1)
}

setAudioVolume = (value) => {
this.audio.volume = value
setAudioVolume = (volumeBarValue) => {
this.audio.volume = this.getListeningVolume(volumeBarValue)
this.setState({
currentAudioVolume: value,
soundValue: value,
currentAudioVolume: volumeBarValue,
soundValue: volumeBarValue,
})

// Update fade-in interval to transition to new volume
if (this.state.currentVolumeFade === VOLUME_FADE.IN) {
this.state.updateIntervalEndVolume &&
this.state.updateIntervalEndVolume(value)
this.state.updateIntervalEndVolume(volumeBarValue)
}
}

Expand All @@ -1069,6 +1069,14 @@ export default class ReactJkMusicPlayer extends PureComponent {
}
}

getListeningVolume = (volumeBarValue) => {
return volumeBarValue ** 2
}

getVolumeBarValue = (listeningVolume) => {
return Math.sqrt(listeningVolume)
}

onAudioReload = () => {
if (this.props.audioLists.length) {
this.handlePlay(PLAY_MODE.singleLoop)
Expand Down Expand Up @@ -1248,7 +1256,7 @@ export default class ReactJkMusicPlayer extends PureComponent {
updateIntervalEndVolume: undefined,
})
// It's possible that the volume level in the UI has changed since beginning of fade
this.audio.volume = this.state.soundValue
this.audio.volume = this.getListeningVolume(this.state.soundValue)
},
)

Expand All @@ -1259,7 +1267,7 @@ export default class ReactJkMusicPlayer extends PureComponent {
} else {
this.setState({ currentVolumeFade: VOLUME_FADE.IN })
const startVolume = isCurrentlyFading ? this.audio.volume : 0
const endVolume = this.state.soundValue
const endVolume = this.getListeningVolume(this.state.soundValue)
// Always fade in from 0 to current volume
const {
fadeInterval: fadeInInterval,
Expand All @@ -1269,7 +1277,6 @@ export default class ReactJkMusicPlayer extends PureComponent {
startVolume,
endVolume,
{
// If starting track from beginning, start immediately without fade-in
duration: fadeIn,
},
() => {
Expand All @@ -1278,7 +1285,7 @@ export default class ReactJkMusicPlayer extends PureComponent {
currentVolumeFadeInterval: undefined,
updateIntervalEndVolume: undefined,
})
this.audio.volume = this.state.soundValue
this.audio.volume = this.getListeningVolume(this.state.soundValue)
},
)

Expand Down Expand Up @@ -1533,11 +1540,12 @@ export default class ReactJkMusicPlayer extends PureComponent {
if (currentVolumeFade !== VOLUME_FADE.NONE) {
return
}
const volumeBarValue = this.getVolumeBarValue(volume)
this.setState({
soundValue: volume,
soundValue: volumeBarValue,
})
if (this.props.onAudioVolumeChange) {
const formattedVolume = parseFloat(volume.toFixed(2))
const formattedVolume = parseFloat(volume.toFixed(4))
this.props.onAudioVolumeChange(formattedVolume)
}
}
Expand Down

0 comments on commit a7b9cec

Please sign in to comment.