how to make a useref function to intial state in react js - reactjs

In the below code i have used frame motion library where in the motion.img element can be dragged
here i need to make a button with onclick listener where once i click the button the img element will be in the intial position.so what should i do in this casetake a Look at this ui for reference
const constraintsRef = useRef(null);
return(
<motion.div class="row md-row-cols-3 row-cols-4 justify-content-center conainer "ref={constraintsRef}>
<motion.img
className="box"
whileHover={{ scale: 1.2 }}
whileTap={{ scale: 0.9 }}
transition={{ type: "spring", stiffness: 400, damping: 17 }}
src={logo1}
height="60"
width="60"
alt=" v"
drag dragConstraints={constraintsRef}
/>
</motion.div>)};
i have tried usestate but it didnt showup in the framer motion docs they used ref function for this
https://codesandbox.io/s/t9uoz?module=%2Fsrc%2FExample.tsx

Related

Animating height using Framer Motion not working in React

So, I have been trying to use Framer Motion for my React project. I basically want to animate the height from 0 to "auto", when the div gets rendered.
I tried the below code, but the height is not getting animated
<motion.div
initial={{ height: 0 }}
animate={{ height: "auto" }}
transition={{ duration: 0.5 }}
key={searchQuery?.length}
>
When I replaced height with width, the animation works fine, but can't figure out why the height is not getting animated. And I was unable to find any proper documentation regarding this.
Here is the CodeSandbox Link for demo.
Fixed versinn
What was wrong?
Your conditional rendering logic was in the wrong place, AnimatePresence works only if its direct child disappears.
exit prop was missing
key prop has to be stable, it can't be the length of the string
overflow: hidden have to be added so the children are invisible
Final code:
export default function App() {
const ref = useRef(null);
const [isActive, setIsActive] = useState(false);
const [searchQuery, setSearchQuery] = useState("");
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<div>
<input
placeholder={"Enter Keyword"}
value={searchQuery}
onChange={(e) => {
setSearchQuery(e.target.value);
}}
/>
<AnimatePresence>
{searchQuery?.length >= 1 && (
<motion.div
style={{ overflow: "hidden" }}
initial={{ height: 0 }}
animate={{ height: "auto" }}
transition={{ duration: 0.5 }}
exit={{ height: 0 }}
key={"container"}
>
{dataList?.map((listItem) => (
<div
style={{
padding: "1rem",
color: "#E090EE",
borderBottom: "1px solid #E1E1E1",
}}
>
{listItem.activity_title}
</div>
))}
</motion.div>
)}
</AnimatePresence>
</div>
</div>
);
}

How to prevent double page loading in React/NextJS + Framer Motion

I'm trying to animate an image gallery with framer-motion.
I'm using AnimatePresence to detect the value change and animate accordingly.
When I click any links on the same page, for example to a related product, the page renders twice.
Without AnimatePresence it works fine. What am I doing wrong here?
This version, without motion works fine, and causes no errors ( but obvs doesn't animate.. )
// useSate - Change Image
const [currentImage, setCurrentImage] = useState(0);
const galleryImages = [
image_one.url,
image_two.url,
image_three.url,
image_four.url,
]
// Click Handler
<div onClick={ () => { setCurrentImage( 1 ) } }></div>
// Gallery Image Container
<div style={{ backgroundImage: "url(" + galleryImages[currentImage] + ")" }}></div>
This version causes the links on the page to trigger a 'double reload', but the gallery works..
<AnimatePresence>
<motion.div
initial={{ opacity: 0, scale: 1.05 }}
animate={{ opacity: 1, scale: 1 }}
transition={{
duration: .4,
ease: "easeInOut"
}}
style={{ backgroundImage: "url(" + galleryImages[currentImage] + ")" }}
key={ currentImage }
>
</motion.div>
</AnimatePresence>
I've also tried using mode="exit" (/exitBeforeEnter), and useEffect.

Animating an image in framer motion

I'm trying to animate an image using framer motion in react
<div className={classes.imgContainer}>
<img src={gradient} id={classes["gradient"]} alt="gradient" />
<motion.img
id={classes["floater"]}
initial={{ y: -10 }}
animate={{ y: 10 }}
transition={{
type: "smooth",
repeatType: "mirror",
duration: 2,
repeat: Infinity,
}}
src={floaterImg}
alt="floater"
/>
</div>
But the code above throws TypeError: "Cannot read properties of undefined (reading 'needsInterpolation')"
Had the same issue after upgrading to next 13. Fixed it by upgrading to the latest version of framer-motion.

React Framer Motion whileInView not working while using X position

I am trying to use whileInView in order to animate some elements on scroll in react.
here is the codesandbox link: https://bz6msx.csb.app/
if you go and check the code then you see that while using whileInView it does not trigger the animation.
is there anything am I missing?
Thanks
I think you received an answer to this, here.
That is not bug. whileInView property is associated with Intersection
Observer API. In your CodeSandBox , h1 tag has initial state with x:
100vh. h1 tag not visible in viewport. only visible element activate
whileInView animation.
There are some tricks.
set 100vw to 95vw. Then element is visible.
<div className="App">
<motion.h1
initial={{
x: "95vw" // set 100vw to 95vw
}}
// This is not working
whileInView={{
x: 0,
transition: {
duration: 1,
type: "spring",
stiffness: 50
}
}}
>
Motion
</motion.h1>
</div>
Set WhileInView Property parent tag.
import "./styles.css";
import { motion } from "framer-motion";
import { useState } from "react";
export default function App() {
const [isInView, setIsInView] = useState(false);
return (
<motion.div
whileInView={() => {
// when element in viewport , set IsInView true!
setIsInView(true);
return {};
}}
className="App"
>
<motion.h1
initial={{
x: "100vw"
}}
// This is working
animate={
isInView && {
x: 0,
transition: {
duration: 1,
type: "spring",
stiffness: 50
}
}}
>
Motion
</motion.h1>
</motion.div>
);
}

Animate input width from right to left framer motion

I'm trying to make my input appears with an animation making its width size going from 0 to 50%. For this, I've used framer-motion. I've managed to make the animation but by default it's growing from the left to the right. Is there any way I could make it change to have it growing from the right to the left ?
sandbox simple reproduction
import { motion } from "framer-motion";
import { useState } from "react";
export default function App() {
const [toggle, setToggle] = useState(false);
return (
<div>
<button onClick={() => setToggle(!toggle)}>toggle input</button>
<div style={{ marginTop: 25 }}>
{toggle && (
<motion.input
initial={{ width: "0%" }}
animate={{ width: "50%" }}
transition={{ duration: 1, origin: 1 }}
/>
)}
</div>
</div>
);
}
Pretty sure it's not the best way of doing this but I think changing the following should fix your problem. Added x with 50vw = 50% of viewport width (0vw = 0% width) for the initial "position" and for animate x with 0 for the ending position as well as width of 50vw.
<motion.input
initial={{ width: "0vw", x: "50vw" }}
animate={{ width: "50vw", x: 0 }}
transition={{ duration: 1, origin: 1 }}
/>
You can find more details about it on the API Documentation of the motion component under Value type conversion https://www.framer.com/docs/component/##value-type-conversion.

Resources