Open codepunkt opened 9 years ago
Something like this? https://gist.github.com/maisano/8faf4bd123fa9842f4ea
I'm afraid i don't know how to use that.
Tried using it as a parent route component in react-router@1.0.0-beta3
, didn't work too well.
@maisano care to help a bit here please?
oof, i should really add some usage docs to that gist.
@gonsfx the RouteTransition
component was written not to be a route component, but a wrapper for rendering children. e.g.:
// in your base route component:
render() {
return (
<div>
{/** ... **/}
<RouteTransition pathname={this.props.location.pathname}>
{this.props.children}
</RouteTransition>
</div>
);
}
Does that mean all children will animate in the same way? (can't have one child come in from the bottom, another from the right)
in this implementation of <RouteTransition>
, all children being added will animate the same. the same goes for children being removed. however, it would be pretty simple to do some path comparisons and pull from a series of preset transition values. you could also pass in the history action for a particular transition.
@chenglou Thanks for pointing me in the right direction @maisano Thanks for your clarification - that works okay-ish but is a good starting point for further inquiry.
Followup questions:
RouteTransition
only transitions the immediate child - what if i'd like to transition multiple child elements in varying dom hierarchy depths differently - such as fading the body whilst transitioning margin-top
on the header, margin-bottom
on the footer and staggering transitions on the menu inside the header?Would we able to see an example using the new api? Struggling to get my head around the changes!
@boyswan not too familiar with the router. I'll defer to @maisano for this one
@boyswan by new api i'm assuming you meant the new react-motion
api. i just updated the gist to reflect those changes, though i haven't tested it. conceptually it's largely the same, though a prop's name changed and you no longer need to access the val
key from the interpolated values.
Perfect, thanks for this!
@maisano I seem to be having the same issue as@gonsfx where the initial route does not load...
@mattapperson the initial route doesn't load or doesn't transition? if it's the latter, i think you can get that by adding defaultStyles
.
@maisano it was an issue with my styles. the absolute included in this component broke stuff
@mattapperson :+1: yea, that component is more of a demo than anything else.
Would the implementation change dramatically if @chenglou's example was modified to make the transition be a horizontal sliding animation instead of a fading one?
Hi @rclai,
Just replace the scale transfom in the render by translateX(``${interpolated[key].x}%``)
.
And replace scale in both willEnter and willLeave methods by respectively x: spring(-100)
and x: spring(100)
.
That should work.
Perhaps I'm missing something, but I'm having an issue with repeating willEnter and willLeave animations for routes. I'm assuming that because react-router@2
, but I need to animate nested routes based on the path segment specifically, and it would be ideal if I could use that portion of the path.
const routerStyles = props => {
const { pathKey, children } = props;
return {
[pathKey]: {
opacity: spring(1),
scale: spring(0),
position: 'relative',
top: spring(0),
children,
},
};
};
const routeWillEnter = (_, { children }) => {
return {
opacity: spring(0),
scale: spring(1.2),
position: 'absolute',
top: 0,
children,
};
};
const routeWillLeave = (_, { children }) => {
return {
opacity: spring(0),
scale: spring(0.9),
position: 'absolute',
top: 0,
children,
};
};
const RouterTransition = props => {
return (
<TransitionMotion
styles={routerStyles(props)}
willEnter={routeWillEnter}
willLeave={routeWillLeave}
>
{interpolated => (
<span>
{Object.keys(interpolated).map(key => {
const {
children,
opacity,
top,
scale,
position,
} = interpolated[key];
return (
<span
key={`${key}-transition`}
style={{
position,
top,
opacity,
transform: `scale(${scale})`,
}}
children={children}
/>
);
})}
</span>
)}
</TransitionMotion>
);
};
@cdebotton it's hard to tell what's wrong from this–what's the usage look like?
@maisano, sure, the implementation looks like this:
render(): any {
const { location, ...props } = this.props;
const pathKey = this.props.location.pathname.replace(/^\//, '')
.split('/').shift();
return (
<div
style={{
backgroundColor: this.props.backgroundColor,
color: this.props.foregroundColor,
}}
className={styles.app}
>
<div
ref={c => this._container = c}
style={{
backgroundColor: this.props.backgroundColor,
color: this.props.foregroundColor,
}}
className={styles.container}
>
<Nav
style={{
zIndex: this.props.video ? 1000 : 0,
}}
/>
/** Implementation begins here **/
<RouterTransition pathKey={pathKey}>
{this.props.children}
</RouterTransition>
/** Implementation ends here **/
</div>
</div>
);
Sorry for so many posts, but I've at least solved for when the problem happens. If I am transitioning between routes, and then click into another route, the leave animation doesn't fire on the route that is already on the DOM. I believe that this is because the key has not been removed yet from the styles configuration object.
When I wait for the transitions to complete, everything behaves as expected.
I know that I could add a counter, or a constantly changing key to the key, but that feels hacky to me.
i'm still a little unclear on what the problem you're having is, but based on animations repeating, i would guess it's because you're potentially clobbering the pathKey
for multiple routes (e.g. you're passing in the same pathKey
for matches at "/foo/bar"
and "/foo/baz"
). why split on slash and return the first element instead of the entire pathname?
How to get this to work with 0.4.* ? TransitionMotion's api changed and I cannot get this example to work anymore :(
yes, we should have an example (indeed, we should also prep an example for their incoming v2 release). I'll start hacking on this today.
This implementation uses 0.4.2 and is used as a wrapper component which takes – amongst other things – Route components.
This is just a simple example, and fades a single component in from 0.75 opacity.
Hope this helps someone.
import React from 'react';
import Pure from 'mixins/Pure';
import { TransitionMotion, spring } from 'react-motion';
const SpringModel = { stiffness: 250, damping: 25, precision: 0.05 };
const XYZTransitionContainer = React.createClass({
mixins: [Pure],
propTypes: {
id: React.PropTypes.string.isRequired,
height: React.PropTypes.number.isRequired
},
willEnter() {
return { opacity: 0.75 };
},
willLeave() {
return { opacity: spring(1, SpringModel) };
},
getStyles() {
const { id, children } = this.props;
return [{
key: id,
style: { opacity: spring(1, SpringModel) },
data: { children }
}];
},
render() {
const { height } = this.props;
return (
<TransitionMotion
styles={ this.getStyles }
willEnter={ this.willEnter }
willLeave={ this.willLeave }>
{ values =>
<div style={{ height }}>
{ values.map(({ key, style, data }) =>
<div
key={ key }
style={{
height,
opacity: style.opacity
}}>
{ data.children }
</div>
)}
</div>
}
</TransitionMotion>
);
}
});
export default XYZTransitionContainer;
FYI, the newest example in the Wiki Gallery is a RM wrapper for RR.
I also saw this posted on twitter today: https://github.com/nanot1m/motions
@andrewgleave - thanks for this! I started doing something like this (except I used a slide transition) and it worked. After maisano released his wrapper I ended up changing to that because it is nicely abstracted
@maisano- Great wrapper!!! I only ran into one issue/improvement which I posted in your repo
Fade in/out:
Unfortunately this is one effect that doesn't look right. I have tried different stiffness/damping settings but when you transition it either moves so quick you don't notice the fade or one page starts to show through the other since it's opacity hasn't set zero yet. Ideally we would want the current route to fade out and once that is complete the new route fade in. I suspect you would need an animation end event to do this (which I believe isn't available yet)? Maybe there is another way to achieve this?
@chenglou - Obviously incredible library but thanks for helping lead us to solutions on how to integrate with major third party components! Your demos are very cool but being able to use react-motion with react-router for example is a big deal. Developers finally have a well designed library to integrate advanced animations in real world apps :)
Expanding upon this concept further doing the following with react-motion would be awesome!
https://www.google.com/design/spec/animation/meaningful-transitions.html
Although maybe this belongs in react-motion-ui-pack :)
Just to note (noted it on the gist a couple of months back): this uses absolute positioning to work. If you don't have the routeTransition around the footer, it won't look correct visually as whatever you wrap the RouteTransition around will go below your footer.
Basically: don't expect to have a static header / footer, and do a fade transition on the content between the header and footer...
Is there some way to avoid position:absolute ? Maybe we would be able to use some callback to fire when leaving finishes and run enter transition right after that?
It's possible to make this work without position:absolute, but it not so reliable solution yet. Maybe it will be usefull. https://github.com/chenglou/react-motion/issues/419
Is there a way to use this with
react-router
to transition between components?e.g. implement a page transition like http://www.semplicelabs.com/ with additional stagger on the menu items?