Achieve a song playback pause fade in fade out effect — electron + Vue write a player (I)

Time:2021-8-31

order

Decided to start blogging, start with something simple.

Today, I’m still thinking about the implementation details of music on various platforms. I found that they will have a short gradual in and out effect when playing and pausing songs. Let’s start to implement it.

Design

At present, a better idea is to call the pause interface of audio element by continuously reducing the volume until it is 0 in a short time when receiving the user‘s playback request, and call the play interface of audio element first when receiving the user’s pause request, and increase the volume to the volume set by the user in a short time

When you think of the need to go through a certain step continuously, two methods emerge in your mind,setTimeOutorsetInterValandrequestAnimationFrame, because there is no time-consuming continuous asynchronous operation, it is not necessary to usesetTimeOutTo avoidsetInterValCumulative effect (if there are these operations, they should be avoided in the main thread).

We hope that the gradual in and out of the audio can be smooth enough to avoid the grainy feeling of sound due to too large volume change interval. Just use itsetInterValThe interval of callback execution is not fixed. It is only when the execution stack is empty that the task of asynchronous queue is executed. However, at present, there are no tasks that will hinder the execution of callback functionsrequestAnimationFrameLet the callback function be called with the refresh of the screen, so that the frequency of volume change becomes fixed, which seems to be smoother (is it really suitable for non animation rendering tasks?). Finally, I feel shallow on paper. I decide to achieve both, and then compare the effects

realization

Let’s take a look at the difference between fade in and fade out and no fade out. Click hereExample

Given below inrequestAnimationFrameFor the implementation under, first declare the required data in the Vue construction option

data () {
    return {
        ...
        Volume: 1, // the song volume set by the user
        fadeVolume: 0, //   The current volume of the song. Unlike volume, this variable records the real-time volume of the song when it fades in and out
        volumeFadeInFlag: null, //   Save song fade timer
        volumeFadeOutFlag: null, //   Save song fade timer
        ...
    }
}

Then it increases or decreases continuously through circulationfadeVolumeUntil it isvolumeOr 0, for example, the fading code is

 songVolumeFadeOut (audio) {
    this.volumeFadeInFlag && cancelAnimationFrame(this.volumeFadeInFlag)
    const _this = this;
    (function fadeOut () {
        if (_this.fadeVolume - 0.02 <= 0) {
            _this.fadeVolume = 0
            audio.volume = _this.fadeVolume
            cancelAnimationFrame(_this.volumeFadeOutFlag)
            _this.volumeFadeOutFlag = null
            audio.pause()
        } else {
            _this.fadeVolume = _this.fadeVolume - 0.02
            _this.fadeVolume = Number(_this.fadeVolume.toFixed(2))
            audio.volume = _this.fadeVolume
            _this.volumeFadeOutFlag = requestAnimationFrame(fadeOut)
        }
    })()
 }
 

Note that you need to clear the fade in cycle before executing the fade out cycle. If you don’t do so, if you click the pause and play buttons, there will be multiple fade in and fade out at the same time, and they can’t meet the termination conditions, so they fall into the dead cycle, because the refresh frequency is about 60 times a second, and the increment is set to 0.02, you can end the fade in and fade out in about one second.

After writing the fade out and fade in code, we need to find the execution time. I put the fade inaudioelementplayEvent, so the fade in code does not need to be called manuallyaudio.play(), put the fade out in the position indicating the audio playback statusplayingIn the listening of variable, fade out is executed when the request for audio pause is received.

onPlay() {
    ...
    //   When the window is minimized or hidden, the requestanimationframe will be delayed until the window is restored, which is not what we want
    if (document.visibilityState == 'visible') {
        this.songVolumeFadeIn(audio)
    } else {
    //   Therefore, when the window is not visible, we use setinterval instead of requestanimation frame
        this.songVolumeFadeInByInterval(audio)
    }
    ...
}
...
watch: {
    playing() {
        ...
        if (document.visibilityState == 'visible') {
            this.songVolumeFadeOut(audio)
        } else {
            this.songVolumeFadeOutByInterval(audio)
        }
        ...
    }
}

As mentioned earlierrequestAnimationFrameIs an API designed for animation

In order to improve performance and battery life, in most browsers, whenrequestAnimationFrame()Run in the Background tab or hidden<iframe>In the middle of the night,requestAnimationFrame()Will be suspended to improve performance and battery life.

If used in ordinary web pagesrequestAnimationFrameTo achieve the audio fade in and fade out effect, of course, no problem (assuming that the user does not have a very fast hand speed, click the play button and instantly cut the label or minimize the browser), but in the actual desktop player, more than one main interface can control the playback and pause of audio, mini window and tray menu can be controlled. At this time, if the main interface is minimized, it will not be performedrequestAnimationFrameLoop, so it is used heredocument.visibilityStateTo determine whether the main interface is visible, and then select whether to use itrequestAnimationFramestillsetInterval

Click here to view the simple versionsource code

Recommended Today

Paper case CMS 3.3.6 release upgrade. Net 5

.Net 5 Microsoft’s. Net 5 has been released and we adapted it for the first time. The biggest change in the new version is to upgrade to Microsoft’s latest. Net 5, and the performance has been significantly improved. So please update your running environment before upgrading to 3.3.6. Upgrade Guide:http://www.zkea.net/zkeacms/document/upgrade Convenient update Paper shell CMS […]