vueuse / motion

🤹 Vue Composables putting your components in motion

Home Page:https://motion.vueuse.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Issue with "visible" / "visible-once" variant

Rene-Roscher opened this issue · comments

Description:
When using the Vueuse/Motion library, I have encountered an issue with the "visible" / "visible-once" variant. Normally, the element should be immediately visible when it is within the viewport. However, the problem occurs where the element is only displayed when I scroll over the viewport.

Steps to reproduce:

Open the relevant page where the element with the "visible" / "visible-once" variant is used.
Ensure that the viewport directly shows the element without the need for scrolling.
Expected behavior:
The element should be immediately visible when it is within the viewport.

Current behavior:
The element is only displayed when scrolling over the viewport. It appears that the "visible" / "visible-once" variant is not functioning as expected.

Additional information:

Used version of Vueuse/Motion library: 2.0.0
Browser and version used: Brave [Version 1.52.130] (Chromium)
Operating system: Windows 10

Notes:
This issue affects the user experience as the element is not immediately visible when the viewport contains it. It would be desirable for the element to be correctly displayed according to the "visible" / "visible-once" variant, without the need for scrolling.

Hey @Rene-Roscher,

I have the same issue, I initially thought it was a user error but it seems like people are also experiencing this.

This issue dates back to September of 2021: #29

It is unfortunate that it hasn't yet been addressed. It is definitely killing this package for me.

@Tahul I found that this issue is found in chromium based browsers (tested in Google Chrome, Microsoft Edge) but not in Firefox.

Yes I would love a fix for this as the rest of the package is so good!

I have the same problem, this bring me to not use this library.

I have the same problem, this bring me to not use this library.

can you tell me which library you are using instead of this one?

Does anyone have a temporary solution for this? This is very unfortunate lol.. 😭

Facing the same issue here. Works fine on Firefox and Safari, broken on all Chromium-based browsers. Happens when navigating back to any previously visited page. Makes the library virtually useless for me... would be great if anyone has a fix or alternative

Hey everyone! I've found a temporary solution for this.. Its not ideal, but it works. Let me first post how this should work if the v-motion module behaved as expected:

How its suppose to work

The following animation should work when the item(s) are in the initial viewport view. However, it does not. Here I have an animation function I simply pass into my project array (v-for loop) using v-motion.

Note this only works with enter, but not visible or visibleOnce

const animation = (i) => ({
  initial: {
    y: 30,
    opacity: 0
  },
  visibleOnce: {
    y: 0,
    opacity: 1,
    transition: {
      type: 'spring',
      delay: 50 * i
    }
  }
})

// template code
<div v-for="(project, i) in projects" :key="project._id" v-motion="animation(i)">

Temporary solution

After a lot messing around, I found that you can use the useMotion composable within an onMounted hook. There might be another way, but so far its the only thing that has worked for me. Now my animation triggers on the initial viewport view and is triggered if it leaves and then come back into the viewport again (if I am using visible)

const animation = (i) => ({
  initial: {
    y: 30,
    opacity: 0
  },
  visibleOnce: {
    y: 0,
    opacity: 1,
    transition: {
      type: 'spring',
      delay: 50 * i
    }
  }
})

onMounted(() => {
  const mediaItems = document.querySelectorAll('.media-item')

  mediaItems.forEach((mediaItem, i) => {
    useMotion(mediaItem, animation(i))
  })
})

// template code
<div v-for="(project, i) in projects" :key="project._id" class="media-item">

Maybe @Tahul you can take a look at this? This is really the only issue that is stopping this library from being perfect :)

Also, @fabienbergerat is correct in that it seems the first solution (how its suppose to work) works fine in Safari and Firefox, but not Chrome. Seems to be a Chrome issue for whatever reason...

Hey everyone! I've found a temporary solution for this.. Its not ideal, but it works. Let me first post how this should work if the v-motion module behaved as expected:

How its suppose to work

The following animation should work when the item(s) are in the initial viewport view. However, it does not. Here I have an animation function I simply pass into my project array (v-for loop) using v-motion.

Note this only works with enter, but not visible or visibleOnce

const animation = (i) => ({
  initial: {
    y: 30,
    opacity: 0
  },
  visibleOnce: {
    y: 0,
    opacity: 1,
    transition: {
      type: 'spring',
      delay: 50 * i
    }
  }
})

// template code
<div v-for="(project, i) in projects" :key="project._id" v-motion="animation(i)">

Temporary solution

After a lot messing around, I found that you can use the useMotion composable within an onMounted hook. There might be another way, but so far its the only thing that has worked for me. Now my animation triggers on the initial viewport view and is triggered if it leaves and then come back into the viewport again (if I am using visible)

const animation = (i) => ({
  initial: {
    y: 30,
    opacity: 0
  },
  visibleOnce: {
    y: 0,
    opacity: 1,
    transition: {
      type: 'spring',
      delay: 50 * i
    }
  }
})

onMounted(() => {
  const mediaItems = document.querySelectorAll('.media-item')

  mediaItems.forEach((mediaItem, i) => {
    useMotion(mediaItem, animation(i))
  })
})

// template code
<div v-for="(project, i) in projects" :key="project._id" class="media-item">

Maybe @Tahul you can take a look at this? This is really the only issue that is stopping this library from being perfect :)

Also, @fabienbergerat is correct in that it seems the first solution (how its suppose to work) works fine in Safari and Firefox, but not Chrome. Seems to be a Chrome issue for whatever reason...

Thanks for this man! You saved my day

commented

@Tahul Will there be a fix for this or should people just drop this package for others that are maintained?

I see this particular issue coming up again and again ever since 2021.

If you know where to point me to in order to fix this, i will gladly have a look myself but this issue is a dealbreaker.

Original issue: #29

commented

i can confirm this, got same problem here

Yep i can confirm it too. Same problem.

Same issue.

Same problem...

+1 also finding this problematic especially when trying to get animations that work equally well in all screen sizes.

const animation = (i) => ({
initial: {
y: 30,
opacity: 0
},
visibleOnce: {
y: 0,
opacity: 1,
transition: {
type: 'spring',
delay: 50 * i
}
}
})

Here's a slightly more vue-esque variation of your solution @rylanharper

    const statEls = [];
    const setEl = (el) => {
        statEls.push(el);
    }
    const animate = (el, i) => useMotion(el, {
        initial: {
            y: 30,
            opacity: 0
        },
        visibleOnce: {
            y: 0,
            opacity: 1,
            transition: {
                type: 'spring',
                delay: 100 * i
            }
        }
    })
    onMounted(() => {
        statEls.forEach(animate);
    });

// template code
<div v-for="(project, i) in projects" :key="project._id" :ref="setEl">

Thanks for the fix!

Another option would be to use the onVnodeMounted hook. Maybe not the best idea as that hook is undocumented, but useful if you want to attach the animation to items that are added to the list after the parent component has been mounted (as the onMounted hook is only called once).

const animation = (i) => ({
  initial: {
    y: 30,
    opacity: 0
  },
  visibleOnce: {
    y: 0,
    opacity: 1,
    transition: {
      type: 'spring',
      delay: 50 * i
    }
  }
})

// template code
<div v-for="(project, i) in projects" :key="project._id" class="media-item" @vnodeMounted="(node) => useMotion(node.el, animation(i))" >

Yeah, came from framer motion, this works ok at first page load, but if you push router and come back, it doesnt work in chrome. Any more elegant solutions? Because at this point if we need to use a non-declaritve way, i rather use gsap all together :p Im not sure where the issue is either, but let us know if PRs are accepted to fix this?

This should be resolved by #171, I have tested it locally in some small test projects and it seems to work as expected. Can someone else check to see if it works in existing projects? Curious to hear if it's a complete fix 😅.