javascriptcss-animationsweb-animationsweb-animations-api

Image slider with Web Animations API


I've used WAAPI to create an image slider for a (kind of) sing along game. The slider is linked with a song, so the animation timing is very important. Using WAAPI keyframes (which are very similar to CSS keyframes) the timing offset is on a scale of 0-1, hence the calculations necessary for creating the keyframes dynamically in the code pen below. The slider should continuously loop each next slide, including sliding from the last slide to the first slide again. The problem is that the animation doesn't seamlessly continue from slide5 back to slide0.

Here is how I dynamically set the keyframes:

        var keyframes = []
        var pause = 0.18
        var anim = 0.02
        var slideHeight = 150
        var translateBy = 0
        var a = {transform: 'translateY(0)'} //set initial keyframe before loop
        keyframes.push(a)
        var offsetPercent = 0 //offset var to increment by anim & pause vars.
        for(let i=0; i<songVars.fileLength; i++) {
            var b = {
                        offset: offsetPercent+= anim, 
                        transform: 'translateY('+ translateBy +'px)'
                    }
            var c = {
                        offset: offsetPercent+= pause, 
                        transform: 'translateY('+ translateBy +'px)'
                    }
            keyframes.push(b, c)
            translateBy-= slideHeight;
        }
        var d = {transform: 'translateY('+ translateBy +'px)'}; 
        keyframes.push(d)

This code pen shows that the image slider does not loop seamlessly from the last image back to the first image. That is because I can't find a way to achieve continuous, seamless looping with the WAAPI keyframes. The first slide (slide0) is initially out of view as the CSS is set to top: 100%; transform: translateY(-100%);. I did this because the slide should begin by sliding up from the bottom of the container div.

I originally had the slides beginning at position 0, so the slide0 does start from the bottom, but it doesnt work with the timing and runs out of time, and also takes a long time for the first slide to get into position: https://codepen.io/nancy-collins/pen/bGVKBQq

I also tried the slides beginning at position -300px, so the slide0 is in view and doesnt slide up from the bottom, but when it reaches slide5 it jumps to slide0, like this: https://codepen.io/nancy-collins/pen/vYNrvaa

I know that sliders are a common discussion on here but there are none with WAAPI. It's a very new API, but should surely be able to achieve a looping slider. Thanks.


Solution

  • For this effect I think there are a couple of approaches you could try. One is to generate different keyframes for each animation (example CodePen here).

    However, I think you might find it easier if you position all the items on top of one another (using position: absolute; top: 0; left: 0 and using position: relative; width: 300px on the parent element). Then you can apply the same animation to each item but simply change the delay so that they are staggered appropriately.

    Using this approach, the translation positions would not change based on the number of slides. You would position all the frames just below the viewport, then animate them up in three steps, and then return them to their original position just below the viewport. The keyframe offsets, however, would change based on the number of slides so that you could create a suitably long "flat" section at the end where you are waiting for the other slides to finish before repeating.