[FEATURE] Improved support for managing both variant-style animations as well as arbitrary-value style animations at the same time
See original GitHub issueIs your feature request related to a problem? Please describe.
This isn’t really a problem, per se, but it is a way to make the declarative component props API work in more situations.
Some background:
framer-motion’s component props API supports two distinct kinds of animations. The first kind is “variant”-based animations, where the different variants capture discrete versions of a particular element. For instance, a component might have the following variants:
- open, closed, big, small
Consumers can animate between these variations using the animate
prop:
// Starting with these variants...
<motion.div variants={variants} animate={['open', 'big']} />
// ...you can then animate over to these
<motion.div variants={variants} animate={['closed', 'small']}/>
It also supports arbitrary animations using the object form of the animate
prop. For instance, the position of an element could be animated based off of a number that’s randomly generated every few seconds:
const [x, setX] = useState(50);
useEffect(() => {
setInterval(() => {
setX(Math.random() * 100);
}, 1000);
}, []);
// As `x` changes arbitrarily, this div will move around the page.
return (<motion.div animate={{ x }) />);
Tthe component API of framer-motion does not support doing both kinds of these animations at the same time, but a slight change to that API could make it so that it does.
Describe the solution you’d like
Updating the custom
prop triggers animations when it changes would allow components to handle both kinds of animations. That way, even when the variants specified in animate
remain constant, they can dynamically update from a value passed in through custom
.
Right now, changes to custom
do not trigger rerenders. View a CodeSandbox demonstrating this here.
However, consider the following:
// Given the following variant, which depends on `custom`:
const someVariants = {
position(xValue) {
return {
x: xValue * 50
};
}
};
// as `xValue ` changes, the `position` variant would animated, even if the
// `animate` prop doesn't change.
<motion.div variants={someVariants} animate="position" custom={xValue} />
View a CodeSandbox demonstrating this change using the code from #264
This particular example is simple enough that you can solve it using existing framer-motion APIs, but the motivation for this change comes from more complex examples; namely, when you also want to use variants. See the CodeSandbox link below for an example of that kind of situation.
Describe alternatives you’ve considered
In the following CodeSandbox, each item in the list has different variants: visible/hidden and big/small. Additionally, the position of the item is determined by an arbitrary function. The CodeSandbox shows how you can write it declaratively using two motion components.
-
Using two motion components. View a CodeSandbox here.
-
An example showing the AnimationControls API View a CodeSandbox here.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:1
- Comments:7
Top GitHub Comments
tbqh…I forget. It looks like that PR is still open, so my guess is this that isn’t possible still. v2 is right around the corner, so maybe it will be introduced then? I haven’t had a chance to look unfortunately! I used to use this lib a lot at work but for the past few months I haven’t had a chance to.
I do remember having some kind of workaround for this. I think I used nested divs:
custom
Np – thanks for considering this change, @mattgperry !
I still think that this would improve the DX of the lib, but I understand you’ve likely got more impactful priorities ✌️
Thanks again for taking the time to think about this issue, as well as all of the amazing work you’ve done on framer-motion!
Update: I just read your comment over on the PR elaborating more on your decision. That makes sense to me!