Transition and Initial are not working - Framer motion - reactjs

If I manually set scale and opacity in my css, the animation is working.
It's why I think that my initial value don't work, and it's really weird because in another file i'm not facing this issue with the same code.
<motion.a
href="#"
className="file"
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
transition={{ delay: 3, duration: 3 }}
variants={{
visible: { opacity: 1, scale: 1 },
hidden: { opacity: 0, scale: 0 },
}}
>
© Sb_2K22<span className="end">.txt</span>
</motion.a>
Also the delay and duration are not working too...
Tell me if you need more information please

Related

Framer-motion: Fire onTap() when click the other button

I have RotatingButton which is turning and changing scale when clicked.
(Rotating has to be slower so I used two motions and added duration to rotate.)
Button is adding +1 to state. ( addValue() )
<div>
<div>
<motion.button
onClick={addValue}
animate={{ rotate: rotation }}
transition={{ duration: 0.5, ease: 'easeIn' }}
>
<motion.div whileTap={{ scale: 0.8 }}>
<RotatingButton />
</motion.div>
</motion.button>
</div>
<div>
<button onClick={removeValue}>{text}</button>
</div>
</div>
But the problem is that I have second button which is removing -1 value from state ( removeValue() ) and it also has to turn and scale the RotatingButton.
Rotating is easy, I added dependency:
const [rotation, setRotation] = useState<number>(0);
and setting rotation on each addValue() and removeValue().
setRotation(rotation + 180);
but the problem is that I couldn't find the way to scale RotatingButton for 0.5 sec for example by triggering whileTap() on when removeValue() is triggered.
I've tried to make scale state and use useEffect nad trigger it when rotation is changing:
useEffect(() => {
setScale(0.8);
setTimeout(() => {
setScale(0);
}, 300);
}, [rotation]);
and I've also tried
const controls = useAnimationControls();
with controls.start, controls.mount etc.
To trigger it other way, with animation to change scale for 0.5 sec when changing the state, skipping whileTap.
I've tried onTapStart() too.
None of that worked.
Please help me.
The way was to use sequence
https://www.framer.com/motion/use-animation-controls/#sequence
const controls = useAnimationControls();
const sequence = async () => {
await controls.start({ scale: 0.8, transition: { duration: 0.5 } });
return await controls.start({ scale: 1, transition: { duration: 0.5 } });
};
and change whileTap() to animate={controls}
<motion.button
onClick={addValue}
animate={{ rotate: rotation }}
transition={{ duration: 0.5, ease: 'easeIn' }}
>
<motion.div animate={controls}>
<RotatingButton />
</motion.div>
</motion.button>

React / Framer Motion - why are my child elements not staggered?

I'm building a balance overview within a financial services application. The content is rendered by passing props into a single <BalanceEntry> component and then mapping all available entries into the page.
Using Framer Motion, I want to stagger the entry animation of each rendered <BalanceEntry> as a child by 0.2 seconds.
<div className="pt-16">
<motion.div
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, x: 1 }}
transition={{
delay: 0.3,
default: { ease: 'easeInOut' },
staggerChildren: 0.2,
}}
>
{TransactionData.map((item) => {
return (
<div key={item.id}>
<motion.div variants={BalanceEntryVariants}>
<BalanceEntry
transactionDate={item.transactionDate}
transactionType={item.transactionType}
transactionID={item.transactionID}
transactionAmount={item.transactionAmount}
transactionIcon={item.transactionIcon}
/>
</motion.div>
</div>
);
})}
</motion.div>
</div>
);
I have created two motion.divs based on multiple suggestions here on SO to achieve the staggering, but I still fail to have each BalanceEntry component animated with staggering, instead they are always animated as a group:
The variants are setup like this:
const BalanceEntryVariants = {
hidden: {
opacity: 0,
y: -20,
},
visible: {
opacity: 1,
x: 1,
transition: {
ease: 'easeInOut',
},
},
};
Where is my mistake to render each individual BalanceEntry staggered happening?
It seems that this can be solved by defining a variant for the parent motion.div as well, perhaps try something like:
const parent = {
visible: {
opacity: 1,
y: -20,
transition: {
when: 'beforeChildren',
staggerChildren: 0.2,
delay: 0.3,
},
},
hidden: {
opacity: 0,
x: 1,
transition: {
when: 'afterChildren',
},
},
};
Add the variant to parent motion.div:
<motion.div initial="hidden" animate="visible" variants={parent}>
...
</motion.div>
Here is a minimized example running on: stackblitz
There might be other issues as well (not sure about the purpose of y: -20 and x: 1), but hopefully this would still help.

framer-motion in nextjs won't animate a margin of -100vh to 0vh but animates 0vh to 100vh just fine

I am trying to animate a navbar to open and close. I have a larger container that animates by changing height, and I want to slide down this inner container while it animates its height. However, the animation only works one way, so when the navbar is closing it animates as if it's sliding up but when it's opening there is no animation.
const innerVariants = {
open: {
marginTop: "0",
},
closed: {
marginTop: "-100vh",
},
};
<motion.div
initial={false}
variants={innerVariants}
animate={isOpen ? "open" : "closed"}
transition={{ duration: 0.5 }}
style={{ height: "100vh" }}
>
</motion.div>
Error Message:
You are trying to animate marginTop from "-100vh" to "0vh". -100vh is not an animatable value - to enable this animation set -100vh to a value animatable to 0vh via the `style` property.
It's hard to tell without seeing more code but you may need to use the window height as a number instead of 100vh as a string.
Something like this:
const windowHeight = window.innerHeight;
const innerVariants = {
open: {
marginTop: 0,
transition: {
duration: 0.5
}
},
closed: {
marginTop: -windowHeight,
transition: {
duration: 0.5
}
}
};
here's a working code sandbox: https://codesandbox.io/s/stackoverflow-framer-motion-in-nextjs-wont-animate-a-margin-of-100vh-to-0vh-but-animates-0vh-eiduvq?file=/src/App.js

Framer-Motion AnimatePresence Choppy Animation

I want to use framer-motion to create a transition where element 2 slides in from the bottom as element 1 slides out to the top when I click next.
I'm using AnimatePresence component to achieve this, but the result is a strangely choppy transition where Element 2 appears in the final position briefly before it starts animating from the bottom.
Code:
<AnimatePresence exitBeforeEnter>
{
active === 0 ? (
<motion.div
key='id_1'
initial={{ opacity: 0 }}
animate={{ opacity: 1, backgroundColor: 'green' }}
exit={{ y: '-100%' }}
transition={{ duration: 2 }}>
Element 1
</motion.div>
)
: (
<motion.div
key='id_2'
initial={{ y: '100%' }}
animate={{ y: 0 }}
transition={{ duration: 2 }}
style={{
backgroundColor: 'purple'
}}>
Element 2
</motion.div>
)
}
</AnimatePresence>
Why does the second element appear briefly at first completely ignoring the initial state?

Animation made using framer motion looks too lagged in reactjs

Here is the website link and as you can see, the intro animations look too laggy. Here is the code:
<motion.div className='pic' initial={{x:window.innerWidth < 996?'0%':'100%'}} animate={{x:'0%'}} transition={{delay:'1.6', type:'spring'}}><img src={blob} alt='hero section image'></img></motion.div>
Even the animations after the hero section don't look nice. I have used the react-intersection-observer to activate the animation on scrolling in this particular code.
<motion.div className='detailed' ref={refdetail} initial={{x:'100%', opacity:'0%'}} animate={{x: inViewdetail? '0%': '100%', opacity:inViewdetail? '100%': '0%'}} transition={{ delay:'1.5'}}>
Recently I have worked with framer.motion and it worked well out in my side.
I think that problem is related to the delay sub-prop you used in transition prop.
Here is my tested codebase with motion.framer which works fine in my side.
<motion.div
key={"setuplayout_motion"}
exit={{ opacity: 0 }}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
>
<SetupLayout setCurrentStep={setCurrentStep} />
</motion.div>
<motion.div
animate={{
x: authType === "sign-in" ? "10px" : "70px",
}}
transition={{
x: { type: "spring", stiffness: 100 },
duration: 0.8,
delay: 0.2,
}}
/>

Resources