New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Animated transitions #17
Comments
@mjackson do you have any examples of doing this anywhere by chance? |
@cavneb We're still working on this. I have a half-finished example, but I couldn't get it working. |
I would also love this feature! |
I was able to achieve this without issue with the React TransitionGroup (I'm using JS-based animations) by simply doing:
|
This actually would have worked before #90 I think, just put |
+1 for the example mention :) |
Sorry, I started to do this but didn't have the time to finish. Glad to see you got it done anyways! |
Seems like wrapping Does anyone else have a better solution to this issue? Would be sad to lose out on the performance boost you get from not applying |
There are necessarily two elements, otherwise the animation isn't possible. You need keys. The DOM diff just updates the changed parts of a node tree. If that's all you're doing, there is no previous element to animate out. Make sense? |
Yeah, makes sense. Thanks :) |
Would be awesome to see an example of react-router and transitions. :-) |
Well, my good sir; I am embarrassed. Thanks! |
@iammerrick np! :) |
@iammerrick there is also this one :P http://jsbin.com/pamon/2 |
Thanks! :-)
|
so this won't work with animations between pages that are handled by the same handler? |
I tried building a version of the example using TransitionGroup's lifecycle hooks rather than CSSTransition and the hooks don't seem to get called. Am I missing something, or is this behavior only supposed to work with CSSTransitionGroup at the moment? |
Is there a way or a pattern to make this more flexible? I don't necessarily want everything under a |
Any guidance on this? |
I'm interested in this too, current example seems outdated #1194 |
working on this in the 1.0 branch, there's no more RouteHandler stuff going On Tue, May 19, 2015 at 8:45 PM, Daniel Belohlavek <notifications@github.com
|
I created a pen with a working example: |
Hey @luisrudge thanks for your answer! I got that far myself but I got several warnings and an error when trying to run the code :(
I read somewhere that might have to do with having duplicate React instances. I'm using Browserify! |
Never saw that. I'm using webpack, but this pen also doesn't throw this errors Enviado pelo meu Windows Phone De: Daniel Belohlavekmailto:notifications@github.com Hey @luisrudge thanks for your answer! I got that far myself but I got several warnings and an error when trying to run the code :(
I read somewhere that might have to do with having duplicate React instances. I'm using Browserify! Reply to this email directly or view it on GitHub: |
How is the progress with animations in |
Check out the oficial example. There are alternatives to react-addons-css-transition-group such as velocity-react and react-motion. Here's a simple example of a
Simply wrap and it's done:
|
If like me you're just trying to get simple CSS transitions to work (especially fade-out) with react-router 2.0, and you don't need the heavy artillery, you can use "react-easy-transition", a very lightweight module that I wrote to solve that. <EasyTransition
path={location.pathname}
initialStyle={{opacity: 0}}
transition="opacity 0.3s ease-in"
finalStyle={{opacity: 1}}
>
{this.props.children}
</EasyTransition> The demo with redux integration |
@misterfresh huge thanks! |
@misterfresh many thanks! |
thanks!!!! |
None of these examples work with asynchronous routing, has anyone got any examples of that? Looking for something that starts fading out before the next chunk has loaded. |
Has anyone been able to crossfade with React Router? Every example I've seen will not fade in the new route until the old route is fully faded out, which flashes the screen in a jarring way. Looking for a crossfade solution! |
The bundled animation example shows that. |
Following the canonical example for animation I noticed that the leave animation is called when the new route could be resolved (e.g. when For me this is very surprising. Is there any way to trigger the leave animation for |
I managed it in the end. Although for my use case I had a swiping transition. Things I learnt:
I went with react-motion, it's the only library that seems to exist that allows you to interrupt animations, even native css animations can't do it, seems animation on the web is seriously lacking, happy to be told I'm wrong. I have an App component that renders all the child components (pages) within it. I added some logic (using redux) that would unmount the current page when a script chunk was loading, this would give me my page swipe out animation before the next chunk has started loading. Then my navigation code looked something like this, i.e. the user would click a 'Next' button and it would fire the below code.
The dispatch updates my app redux state so that my App component knows to unmount it's current page. When the next chunk has loaded 'script chunk loading' is turned off in state and the next page is animated in. react-motion takes care of the animating quite elegantly, although it took me a fair bit of time figuring out how their The downside to this method, is the delay the user gets between clicking to navigate and the url in the address bar changing (although the unmount animation is instant). And having to wrap navigation points in chunk loading statements. I think this is the best we can do at the moment though. |
@AlastairTaft That's gold! Especially the parts about what is interruptible and what not. Thank you. I also tried |
I created a import React, { Component } from 'react'
import { TransitionMotion, spring, presets } from 'react-motion'
// These are just some convenience functions to help calculate the left position of the
// animation
import { getPanelWidth, calculatePanelToEdgeOfScreenDistance } from './../../Panel'
// The css just makes the leaving component `position:absolute` so that it doesn't
// take up space in the document
require('./PanelsTransition.css')
const calculatePosition = (x, delta) => {
// If we're not in a browser environment don't do anything
if (typeof window === 'undefined') return 0;
const dist = calculatePanelToEdgeOfScreenDistance()
return dist * x * delta
};
class PanelsTransition extends Component {
static propTypes = {
/**
* The direction of navigation, 1 for forwards, -1 for backwards
*/
delta: React.PropTypes.number,
/**
* Set this to true to animate on initial render
*/
animateOnInitialRender: React.PropTypes.bool,
};
static defaultProps = {
animateOnInitialRender: false,
};
willLeave = () => {
return {
transitionAmount: spring(-1, {stiffness: 300, damping: 26}),
finalAmount: -1,
}
};
willEnter = () => {
return {
transitionAmount: 1,
finalAmount: 1,
}
};
render = () => {
const { pathname, delta, animateOnInitialRender } = this.props
// If it isn't an initial render then animate in the first component
if (animateOnInitialRender){
var defaultStyles = [{
key: pathname,
style: {
transitionAmount: spring(1, presets.gentle),
finalAmount: 1,
},
data: {
component: this.props.children,
},
}]
}
return <TransitionMotion
willLeave={this.willLeave}
willEnter={this.willEnter}
defaultStyles={defaultStyles}
styles={[{
key: pathname,
style: {
transitionAmount: spring(0, presets.gentle),
finalAmount: 0,
},
data: {
component: this.props.children,
},
}]}>
{interpolatedStyles => {
return <div>
{interpolatedStyles.map(config => {
const isLeaving = config.style.finalAmount == -1
return <div
// Makes leaving components absolute so they don't take up space
// in the document
className={`PanelsTransition${isLeaving ? '-leaving' : ''}`}
key={config.key}
>
<div style={{
position: 'relative',
left: calculatePosition(config.style.transitionAmount, delta),
}}>
{config.data.component}
</div>
</div>
})}
</div>
}}
</TransitionMotion>
}
}
export default PanelsTransition In my App component I then had something like this class App extends Component {
render = () => {
const { scriptChunkIsLoading } = this.props
// I've got my routing state in redux and can figure out
// the direction of navigation there but this can come from
// anywhere or be passed in as props
const state = this.context.store.getState()
const { delta, initialRender } = state.routing
var pathname = this.props.location.pathname
// Ensure the path always starts with a slash, I've seen it be inconsistent
// sometimes
if (pathname.startsWith('/') == false)
pathname = '/' + pathname
// Make sure our child element has a key that relates to our page
// this is important
var child = React.cloneElement(this.props.children, {
key: pathname,
})
if (scriptChunkIsLoading){
// This is kind of crude, it's just means we override our child element and
// render an empty div that takes up space in the document,
// helps with the unmount animation. Only useful for me as a way of pushing
// a footer element down the screen, rendering null would work just as well
var child = <div
style={{
height: (typeof document !== 'undefined') ? document.body.clientHeight : 1280
}}
/>
pathname = "animationPlaceholder"
}
return <div>
...
<PanelsTransition
pathname={pathname}
delta={delta}
>
{child}
</PanelsTransition>
...
</div>
}
} It doesn't work perfectly, I plan on improving it, the direction of the animation is wrong when the animation get's interrupted, but apart from that it seems to work well, the finalAmount bit is a bit of a hacky work in progress, that would likely change once I fix this up. The react-motion api feels a bit awkward and that maybe I'm not using it the way it's intended especially with the way I've hijacked their data key to keep a reference to the component which then gets rendered, but hell it works. |
We looked at a few libs out there for this |
@stooboo |
@donaldpipowitch cheers I missed that - thanks for the heads-up |
It should be really easy to animate between routes when the URL changes, preferably using
ReactCSSTransitionGroup
.The text was updated successfully, but these errors were encountered: