I'm trying to learn how to use react-spring. Let's say that I have three divs to animate.
<a.div style={trans1}>
<a.div style={trans2}>
<a.div style={trans3}>
and trans1 has the following configuration…
const [clicked, toggle] = useState(null)
const { x } = useSpring({
from: { x: 0 },
x: clicked ? 1 : 0,
config: { duration: 500 },
})
const trans1 = {
transform: x
.interpolate({
range: [0, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 1],
output: [1, 0.97, 0.9, 1.1, 0.9, 1.1, 1.03, 1],
})
.interpolate((x) => `scale(${x})`),
}
What's the best way to implement the same type of animation on the second and third divs without duplicating all that code? How do I make multiple instances of the same spring for use on multiple Dom objects without triggering them all at the same time? I certainly don't want to duplicate a full set of code for each item, right?
Do I need to create a function that accepts a parameter that can switch the arguments in the config on the fly? 🤷🏽♂️ Any help is appreciated.
Here's a live example: https://codesandbox.io/s/optimistic-bassi-brnle
How do I make the left & right sides animate one at a time without creating duplicate code?
The first possibility would be to separate the style and give it to more than one div. Its drawback is, that they would behave exactly the same at the same time.
const style = {
opacity: x.interpolate({ range: [0, 1], output: [0.3, 1] }),
transform: x
.interpolate({
range: [0, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 1],
output: [1, 0.97, 0.9, 1.1, 0.9, 1.1, 1.03, 1]
})
.interpolate(x => `scale(${x})`)
};
return (
<div onClick={() => toggle(!state)}>
<animated.div
style={style}>
click
</animated.div>
<animated.div
style={style}>
click
</animated.div>
</div>
)
The second option is, that you create a new component with the click and spring logic. This way you write the logic once and you can use it multiple time. I introduced a text attribute also to make different text for the component.
const AnimText = ({text}) => {
const [state, toggle] = useState(true)
const { x } = useSpring({ from: { x: 0 }, x: state ? 1 : 0, config: { duration: 1000 } })
return (
<div onClick={() => toggle(!state)}>
<animated.div
style={{
opacity: x.interpolate({ range: [0, 1], output: [0.3, 1] }),
transform: x
.interpolate({
range: [0, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 1],
output: [1, 0.97, 0.9, 1.1, 0.9, 1.1, 1.03, 1]
})
.interpolate(x => `scale(${x})`)
}}>
{text}
</animated.div>
</div>
)
}
function Demo() {
return (
<div>
<AnimText text={'click1'}/>
<AnimText text={'click2'}/>
<AnimText text={'click3'}/>
</div>
)
}
here is the example: https://codesandbox.io/s/divine-water-n1b6x