vueuse / motion

🤹 Vue Composables putting your components in motion
https://motion.vueuse.org
MIT License
2.27k stars 79 forks source link

Is there a "start" equivalent to onComplete? #113

Open kalnode opened 1 year ago

kalnode commented 1 year ago

I'm displaying staggered-animations for grid views, and using @vueuse/motion for animating the grid items.

Everything is working, however I just want to optimize and get more precise.

For reasons, I track the animation state of each grid item, using HTML data (e.g. data-animating="true"), such that animated grid items appear like so:

<div data-index="4" style="opacity: 1; height: 0px; transform: translateZ(0px);" data-animating="false">
    my item
</div>

However, on each staggered item, the animation state is set instantly, as opposed to only being set when the actual @vueuse/motion animation begins (preferred). As a test, if delay were set to 5 seconds, the issue is really apparent... grid items are marked as "animating=true" even though no motion is occurring on them yet (until the delay passes)

In the docs, there's an onComplete event mentioned for post-animation logic, which works.

Is there an onStart event, or some other way to detect the actual-start of animation?

transition: {
    delay: delay,

    // Does something like this exist?
    onStart: () => {
        el.dataset.animating = true
    }

}

I'd rather not have a separate setTimeout wrapping the data change; this seems... wrong.

More complete code:


  enter(el, done) {

    // Each grid item is delayed in order to create a staggering effect
    const index = el.dataset.index || 1
    var delay = index * this.duration

    // Set a grid item's animating state
    // PROBLEM: This occurs instantly, as opposed to when the useMotion animation actually starts
    el.dataset.animating = true

    useMotion(el, {
        initial: {
            opacity: 0,
            y: 100
        },
        enter: {
            opacity: 1,
            y: 0,
            transition: {
                delay: delay,

                // IDEALLY something like this exists.
                onStart: () => {
                    el.dataset.animating = true
                },

                // All of the below works
                onComplete: () => {
                    el.dataset.animating = false
                    done() // Informs the Vue TransitionGroup the anim is done it's work
                }
            }
        }
    })
}