Closed chenglou closed 9 years ago
Quick question, is there any reason why the call to rAF
couldn't be disabled on componentDidUpdate
and enabled when componentWillUpdate
(apart from componentDidMount
)?
Not sure what you mean? Currently the rAF doesn't stop at all until unmount. But still, why disabling it on didUpdate?
Because it will re-render everything down the tree on every cycle and if I want the animation to be a once off, then it should stop right after it reached the end value, shouldn't it? I don't know if you remember about the panels question I asked you at the end of the conference regarding snapping, essentially, every panel renders custom things inside itself. If I'm surrounding them by Spring
I get never-ending render calls to every one of its children :(. Am I trying to use the library in a way it wasn't intended?
Yes, of course I will stop rAF-ing when I detect that the velocities have all gone to zero =). I just didn't do it now because there are other stuff to fix, simple as that. #12
:D perfect, thanks! Thought I was missing something there...
Not sure if it's in the works, but I think it would be beneficial to take care of all vendor prefixing and allow users to pass values similar to these:
<Spring destinationValue={prevTickTops => ({
a: {translateX: {destValue: 35, springConfig: {stiffness: 10}}},
b: {scale: {destValue: 1, springConfig: {stiffness: 20}}}
})}>
This is taking inspiration from animation libraries like http://julian.com/research/velocity/. Not sure how the final API will look, but will there be wrappers that allow appear, enter, and leave animations like TransitionGroup does? I tried taking this on here with Velocity https://github.com/souporserious/velocitytransitiongroup. So being able to provide a map of values that should change on appear, maybe something like this:
<Spring destinationValue={prevTickTops => ({
appear: {
opacity: {destValue: 1, springConfig: {stiffness: 10}},
translateY: {destValue: 0, springConfig: {stiffness: 10}},
}
})}>
Also, what about being able to provide predefined animations that people could create and share. This was one reason I've been trying to get Velocity to play well with React. Loved that a set of animations could be created and reused/updated in one place.
TransitionSpring
works and is currently undocumented. Stay tuned =).
There won't be a core built-in API for taking care of vendor prefixes, because I made sure doing so would be trivial:
<div style={...prefix('translate', [0, currentValues.x., 0]), top: otherValue}/>
This is trivial to implement. It returns an object that you'll spread onto your existing style. You generate these at the bottom level when you receive your interpolated values, instead of prescribing them into your (arbitrary) initial data structure. If there's enough demand I'll expose that as a helper.
Regarding predefined animation: is this enough? Create a new component that wraps around Spring by pre-setting some values for destinationValue
. That should do what you want, right?
Awesome. Yeah I was just thinking of giving users that don't want to set up anything and just add animations an easy way to do so. Creating a wrapper component for whatever predefined animations you need makes total sense though. Then you could just have custom props for whatever your animation is. Excited to see more docs on it :)
Closed because not an issue. But will always welcome questioning of the general API here!
This is a very new library. If you were curious as to how its design came to be, you're at the right place!
This issue's focused on the declarative tweening itself. I'll make another one for unmounting animation. For reference, check my React-Europe talk on animation.
I've partitioned the possible APIs into representative categories, then trimmed away the invalid ones to come to what roughly looks like the current state of the API. The APIs are all focused on the physics of a spring.
Note: if there's ever an oversight in my reasoning that results in my trimming a possibly valid API, please do point out!
Note 2: this is a simplified version. Feel free to ask questions on the unclear part.
Here are the specific criteria:
top
should be able to depend on item2's current interpolated value ofwidth
. This seems a bit random, but it's needed to do the real physics version of the staggered animation (where one thing animates after another). See the chat headdemo1.jsx
.Please also point out if my criteria are too extreme and cover unnecessary use-cases.
1 Put style directly on children
1.1Directly style on DOM components1.1.1Can't interpolate.
1.1.2Means
scalarValue
has to be in some configuration, in which case the constraint of styling directly on DOM components doesn't apply. Scratched. Generalized version below in point 2.1.2Use wrapper component1.2.1Thing
wrapper provided by Spring, somehow. It'll interpolate from whatever current value (stored inThing
's state) to thedestinationValue
. Unfortunately, can't animatetop
unlessThing
passes props to childdiv
; next point.1.2.2
Compute
Thing
using HOC. Supports both flat list and tree children. How to do dependencies on currently transitioning values? Can't, unless with a dedicated binding API. Let's not do bindings for now?2 Put style inside a configuration + let user manipulate and generate children
This implies the configuration is stored somewhere inside owner state, callback passed to generate children, context, etc. They're mostly equivalent (?).
2.1Use wrapper componentNo need for wrapper. We can directly point to where we want to style.
2.2No wrapper2.2.1Supports both flat list and tree children. Works with dependencies between final values: generate your data however you want before passing it to
destinationValue
. Doesn't work with dependencies between current values (this is the real criteria). You don't know whatx
's current interpolated value is until you pass the final structure to spring for the interpolation. The chat head demo cheats by using the previous tick's interpolated value (exposed here asprevTickTops
, so there's actually a small delay. But maybe this is good enough for most cases? Can't control granularity. Scratched.2.2.2 Above, take 2
More or less what this library uses. This solves the previous granularity problem.
3Mixin + state3.3tween-state"Scratched" in the sense that this is already an established library. Mixins are getting deprecated so this won't be a viable solution in the future. Children functions (as seen above in 2.2.1 and 2.2.2) are a good alternative, which keeps the state inside the wrapper component instead of in the owner's state. The only caveat of keeping the state inside the wrapper is that others can't easily read into that state; you can still do this though:
Which is enough for most cases, from my experience.