react-spring
react-spring copied to clipboard
[bug]: useTrail does not work correctly (spring values are weaker the more trails you have)
🤓 Question
What is the proper way to loop a Trail in v9.0? I've had success with the loop prop for Springs but I'm having difficulty using it with a Trail.
const paths = [...]
<Trail
loop
items={paths}
from={{ opacity: 0.2, y: 0, stroke: 'rgba(255,75,75,1)'}}
to={{ opacity: 1, y: 30, stroke: 'rgba(80,80,80,.35)'}}
>
{(item, index) => ({ y, opacity, stroke }) => (
<animated.path
style={{
opacity,
transform: y.interpolate(y => `translateY(${ y}px`),
}}
d={item}
fill="black"
stroke={stroke}
stroke-width={3}
/>
)}
</Trail>
This code runs the full animation once, but on subsequent loops, only the first few elements in the array are animated. I've tried playing around with delay and duration and it seems to improve the animation somewhat but the latter items in the array only partially animate. I also tried initially setting loop to false, then toggling it to true in the onRest function, but this doesn't loop at all.
Here is a link to the sandbox: https://codesandbox.io/s/tender-https-55nmz?file=/src/LoopedTrail.js
Seems like a bug that loop={true}
doesn't work, but I would need to dig deeper to confirm that.
loop={{ reverse: true }}
seems to work as expected, though.
Thanks for looking into this. It does seem like there is weird behavior going on with loop={true}
.
Not working via hook api either, but seems its only related to usage with state, using to / from works
i.e. this doesn't loop (loding here is from const [loading, setLoading] = useState(true)
)
const spinerProps = useSpring({
rotate: loading ? 360 : 0,
config: { duration: 1000 },
loop: true
});
but this does
const spinerProps = useSpring({
from: { rotate: 0 },
to: { rotate: 360 },
config: { duration: 1000 },
loop: true
});
@IljaDaderko do you have a codesandbox you could share? Preferably using our most up to date version of the library.
Could I ask if there's an easy way to stagger a sequence of springs? As far as I can tell, useTrail doesn't fit my use-case, because it seems to decrease the intensity of the springs further down the trail, whereas I wish the springs to act equally, but just with a set time offset between the start of them.
From discord. Possibly helpful
It was me that left the above comment. There's a comment earlier up that says
loop={{ reverse: true }} seems to work as expected, though.
but this isn't true. To restate, the intensity of the springs at the end of the trail is reduced.
The code in https://github.com/pmndrs/react-spring/blob/master/packages/core/src/hooks/useTrail.ts
has;
if (parent) props.to = parent.springs
And mathematically, I can see why this is happening. As each subsequent strings domain is restricted slightly by it's parent. Say a first spring has gone from 0 to 100, and a second spring is intended to go from 0 to 100 also, but in fact it is more like 0 to 95, because the parent has begun returning towards 0 before the second spring reaches 100. And the value of the 2nd spring is following the parent, rather than the config of the parent with an offset. And multiply the effect for each spring.
I can't see off the top of my head a simple way to make useChain work with loop: { reverse: true } (or {loop: true}, without completely rewriting the implementation.
useTrail is fantastic for the trailing spring effect, but I wonder whether introducing a linear offset
config value in combination with useSprings would fit the desired use case of multiple looping springs with an offset better.
(I've also tried using duration + progress to simulate an initial delay, but setting progress and looping seems to restrict the domain of the spring values)
I found a solution to my problem (though I think it's still a little buggy, not sure).
Am sharing here because even though it isn't a solution to this specific useTrail bug, I believe that it's a solution to the same sort of problem.
To get my staggered springs, I set delay: 50 * index
in root of config object, then loop: { reverse: true, delay: 0}
for loop configuration (which is only referred to at the end of the first animation, which is why the root delay is respected.