Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use non-linear volume slider #266

Merged
merged 2 commits into from
Jan 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
})
})
3 changes: 2 additions & 1 deletion src/components/PlayerMobile.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const PlayerMobile = ({
locale,
toggleMode,
renderAudioTitle,
actionButtonIcon,
}) => (
<div className={cls(prefix, { 'default-bg': !glassBg, 'glass-bg': glassBg })}>
<PlayModeTip
Expand Down Expand Up @@ -90,7 +91,7 @@ const PlayerMobile = ({
title={playing ? locale.clickToPauseText : locale.clickToPlayText}
onClick={onPlay}
>
{playing ? icon.pause : icon.play}
{actionButtonIcon}
</span>
)}
<span
Expand Down
31 changes: 20 additions & 11 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ export default class ReactJkMusicPlayer extends PureComponent {
locale={locale}
toggleMode={toggleMode}
renderAudioTitle={this.renderAudioTitle}
actionButtonIcon={actionButtonIcon}
/>
)}

Expand Down Expand Up @@ -1042,17 +1043,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 +1070,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 +1257,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 +1268,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 +1278,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 +1286,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 +1541,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