GithubHelp home page GithubHelp logo

Comments (26)

JurJean avatar JurJean commented on June 7, 2024 41

The solution from @akeelm is very nice, but I still had a problem with the footer of the page to toggle up and down. Using code below this is fixed.

                <RouteTransition
                    pathname={this.props.location.pathname}
                    atEnter={{ opacity: 0, foo: 0 }}
                    atLeave={{ opacity: 0, foo: 2 }}
                    atActive={{ opacity: 1, foo: 1 }}
                    mapStyles={(styles) => {
                    return {
                        position: (styles.foo <= 1) ? 'relative': 'absolute',
                        width: '100%',
                        height: '100%',
                        opacity: styles.opacity
                    }
                    }}>

I only still have the footer problem when I toggle routes really quick.

from react-router-transition.

albermav avatar albermav commented on June 7, 2024 25

I have a similar solution, it just fades only the appearing div, and hides the older one:

<RouteTransition
  pathname={this.props.location.pathname}
  atEnter={{ opacity: 0 }}
  atLeave={{ opacity: 2 }}
  atActive={{ opacity: 1 }}
  mapStyles={styles => {
    if(styles.opacity > 1){
      return { display: 'none'}
    }
    return { opacity: styles.opacity}
  }}
>
  {this.props.children}
</RouteTransition>

from react-router-transition.

amorino avatar amorino commented on June 7, 2024 10

I think that the issue he's referring (it's just a guess) is this:
https://gfycat.com/JadedUnrealisticBoto
Without an absolute position, this will happen. (This is using the presets.pop)

from react-router-transition.

Xerios avatar Xerios commented on June 7, 2024 3

Unfortunately, I didn't save my code because I had changed my mind about using transitions, but you should be able to do it by doing something like:

// Name of the container, forgot the name
.container {
  display: grid;
  grid-template-areas:"MyCustomAreaName";
}

// Forces all children under container to be in the same space/area
.container > div{
  grid-area: MyCustomAreaName;
}

Note that I don't remember the names of the classes, so I suggest you check them using the Inspector, the child class should be the one that has opacity and all the stuff, while the parent is the container.

Also if you want a wider browser support, you should do the same thing without using "area" feature. ( e.g. grid-template-columns and things like that )

from react-router-transition.

aakarim avatar aakarim commented on June 7, 2024 1

I have modified @JurJean 's solution with a pop config. Works great. Same issue with fast route transitions, though (which is a shame, as one of the motivations for react-motion was to improve UX for cancelled transitions).

const popConfig = { stiffness: 360, damping: 25 };

export const pop = {
  atEnter: {
    transitionIndex: 0,
    scale: 0.8,
    opacity: 0,
  },
  atLeave: {
    scale: spring(0.8, popConfig),
    opacity: spring(0, popConfig),
    transitionIndex: 2,
  },
  atActive: {
    scale: spring(1, popConfig),
    opacity: 1,
    transitionIndex: 1,
  },
  mapStyles: styles => ({
    position: styles.transitionIndex <= 1 ? 'relative' : 'absolute',
    width: '100%',
    height: '100%',
    transform: `scale(${styles.scale})`,
    opacity: styles.opacity,
  }),
};

from react-router-transition.

abelovic avatar abelovic commented on June 7, 2024

I achieved this by applying the css to the inner div (created in renderRoute). To do this I added the css through mapStyles in my presets (see noTransition below):

const fadeTransitionConfig = { stiffness: 200, damping: 22 };

const popTransitionConfig = { stiffness: 360, damping: 25 };

const slideTransitionConfig = { stiffness: 330, damping: 30 };

noTransition = {

atEnter: {
    opacity: 1,
    scale: 1,
    offset: 0
},
atLeave: {
    opacity: spring(1, fadeTransitionConfig),
    scale: spring(1, popTransitionConfig),
    offset: spring(0, slideTransitionConfig)
},
atActive: {
    opacity: spring(1, fadeTransitionConfig),
    scale: spring(1, popTransitionConfig),
    offset: spring(0, slideTransitionConfig)
},
mapStyles(styles) {

    return {
        position: 'absolute',
        boxSizing: 'border-box',
        width: '100%',
        height: '100%',
        opacity: styles.opacity,
        transform: 'translateX(' + styles.offset + '%) scale(' + styles.scale + ')'
    }
}

};

fadeTransition = {

atEnter: Object.assign({}, noTransition.atEnter, { opacity: 0 }),

atLeave: Object.assign({}, noTransition.atLeave, { opacity: spring(0, fadeTransitionConfig) }),

atActive: Object.assign({}, noTransition.atLeave, { opacity: spring(1, fadeTransitionConfig) }),

mapStyles: noTransition.mapStyles

};

popTransition = {

atEnter: Object.assign({}, noTransition.atEnter, { scale: 0.8 }),

atLeave: Object.assign({}, noTransition.atLeave, { scale: spring(0.8, popTransitionConfig) }),

atActive: Object.assign({}, noTransition.atLeave, { scale: spring(1, popTransitionConfig) }),

mapStyles: noTransition.mapStyles

};

slideLeftTransition = {

atEnter: Object.assign({}, noTransition.atEnter, { offset: 100 }),

atLeave: Object.assign({}, noTransition.atLeave, { offset: spring(-100, slideTransitionConfig) }),

atActive: Object.assign({}, noTransition.atLeave, { offset: spring(0, slideTransitionConfig) }),

mapStyles: noTransition.mapStyles

};

slideRightTransition = {

atEnter: Object.assign({}, noTransition.atEnter, { offset: -100 }),

atLeave: Object.assign({}, noTransition.atLeave, { offset: spring(100, slideTransitionConfig) }),

atActive: Object.assign({}, noTransition.atLeave, { offset: spring(0, slideTransitionConfig) }),

mapStyles: noTransition.mapStyles

};

Implementation:

                    <RouteTransition pathname={this.props.location.pathname} {...this.state.transition}>
                        {
                            React.cloneElement(this.props.children, {setTransition: this.setTransition})
                        }
                    </RouteTransition>

From the child I pass the preset when I click on the react-router link for example, and set whatever transition state I want on RouteTransition

@maisano - I ended up doing the above (having a base i.e. 'noTransition') because

  1. My app base has a RouteTransition but I may not want to transition so basically that is the default. Avoids having to change the structure of the container
  2. More importantly, I found that if I only mapped the styles for the particular transition and I switched between "different ones" i.e. fade and slide it wouldn't transition correctly. I also avoided React complaining that I mutated the props because they are different ;) This fixed it and it seems to work well now

Would like to hear your thoughts on this approach i.e. performance considerations interpolating props that don't actually change. I suspect it shouldn't be an issue but not 100% sure.

Thanks for this wrapper - excellent work!

from react-router-transition.

maisano avatar maisano commented on June 7, 2024

@arkist: hm, i haven't given this a ton of thought–to be honest, most of the times i have animated routes, they've been wrapped in such a way where height was not an issue (they made up the entire page or the overflow was scrollable, etc). can you give some more background into your layout/how you're using this?

@abelovic: i'm glad you're enjoying the project! thanks for the feedback. you're correct in your approach if you want to dynamically toggle between different transition settings–react-motion requires the same keys to interpolate, and introducing new ones/removing old ones won't work.

as per your question on performance, i don't see this being an issue. the api recently changed and i haven't looked at the internals since, though i recall TransitionMotion only needing to interpolate keys when their destination values change. in this example, nothing changes so you should be fine.

one small thing i did notice is that you're cloning children to pass in the setTransition callback–if you wanted to avoid this you could use state from history instead, pulling it out in your root component as needed, e.g. using a Link with a state prop (<Link to={path} state={{transition: 'slideLeft'}}>) where you reference that state in your handler via this.props.history.state.transition.

from react-router-transition.

maisano avatar maisano commented on June 7, 2024

@amorino i debated for a while whether to add absolute positions to the presets, or even include the presets at all. it probably makes more sense to add position: absolute to the mapStyles of each preset. it's easy enough to override and they're sort of broken without. feel free to pr or i can update this sometime over the weekend.

from react-router-transition.

arkist avatar arkist commented on June 7, 2024

@amorino exactly. that's the what I encountered.
@maisano I'm a newbie in motion/transitioning so don't know this issue is common or not. see below codes, please.

What I learn from @abelovic's code is set position: absolute; width: 100%; height: 100% and put all the Component inside of <RouteTransition /> works fine. thanks! and noTransition-default strategy looks good.

but I think it seems to be still a problem: how about nested Component's transition? (not about path)

// <Header/> and <Footer/> don't need transition (always there)
// so they're on outside of <RouteTransition />.
// in this case, you can't set `position: absolute` to route because of Header&Footer.
<Header /> 
<RouteTransition
  pathname={this.props.location.pathname}
  atEnter={{opacity: 0, position: 'relative'}}
  atLeave={{opacity: 0, position: 'absolute'}}
  atActive={{opacity: 1, position: 'relative'}}
  mapStyles={styles => {
    return {
      position: styles.position,  // so I wanna something like this but it is impossible! :(
      opacity: styles.opacity
    };
  }}
>
  {this.props.children}
</RouteTransition>
<Footer />

from react-router-transition.

maisano avatar maisano commented on June 7, 2024

@arkist: ah, got it. so the issue with the code posted is that the objects that get passed to atEnter, atLeave and atActive get passed to react-motion for numeric interpolation–this won't work with strings.

i'm not currently sure the best way to handle dynamic, unbounded route heights, though i'm sure this is a common use case. i'll have to give it some more thought.

from react-router-transition.

arkist avatar arkist commented on June 7, 2024

@maisano good :) I'll try to find a way, too. thanks for this project!

from react-router-transition.

abelovic avatar abelovic commented on June 7, 2024

@maisano - thanks for the tip that is a much cleaner way to do it :) The API of react router changed in 2.0 so if anyone is interested this is what I did:

The mixin ContextRoute is deprecated so you will have to get the location object by passing context (its explained in the 2.0.0 change docs)

@arkist - I actually transition my header so the label and buttons etc... are encapsulated inside the react component (my view). If you do this one trick I did is to make the container color the same color as the header otherwise you will see the white background (or whatever color your container is) as the transition occurs.

However it sounds like you would rather have a fixed header where the content is the same for all views you transition to i.e. a common menu or application header

Could you not just do the following (untested)?

.header {
height: 50px
top: 0
position: absolute
}

/* this is passed using mapStyles /
.route-transition {
height: calc(100% - 100px) /
height of header and footer - since it is app specific probably ok to just add it to your presets? */
top: 50px
position: absolute
}

.footer {
height: 50px
bottom: 0
position: absolute
}

from react-router-transition.

abelovic avatar abelovic commented on June 7, 2024

Sorry code snippet got removed

<Link to={{ pathname: '/Home', state: {transition: slideRight} }} />

from react-router-transition.

arkist avatar arkist commented on June 7, 2024

@abelovic thanks for the awesome tip! :)
browser support is a problem only. http://caniuse.com/#search=calc

from react-router-transition.

abelovic avatar abelovic commented on June 7, 2024

Well looks like you would mainly loose Opera mini (Blackberry I think) and IE 8 support but look at this:

https://facebook.github.io/react/blog/2016/01/12/discontinuing-ie8-support.html

For me this is not a problem and I use calc all the time. If you do need to support these browsers however you might be able to use something like:

https://github.com/souporserious/react-measure

and just do the calculations in react :)

from react-router-transition.

JoeMattie avatar JoeMattie commented on June 7, 2024

Just my $0.02:

Instead of percentage I am using:

height:calc(100vh - 50px);

in my mapStyles() function instead of percentage. This makes it so that you don't have to worry about the geometry of the parent component. (100vh is the height of the window in pixels, 50px is the height of my header)

from react-router-transition.

haustraliaer avatar haustraliaer commented on June 7, 2024

This may not be the best solution - but I managed to get @arkist's desired effect by swapping the non-numeric values when one of the animating properties reached a desired value inside the mapStyles function:

<RouteTransition
  pathname={this.props.location.pathname}
  atEnter={{ opacity: 0 }}
  atLeave={{ opacity: 0 }}
  atActive={{ opacity: 1 }}
  mapStyles={(styles) => {
    return {
      position: (styles.opacity === 1) ? undefined: 'absolute',
      width: (styles.opacity === 1) ? undefined : '100%',
      height: (styles.opacity === 1) ? undefined : '100%',
      opacity: styles.opacity,
    }
  }}>
    {this.props.children}
</RouteTransition>

Now I don't need to worry about my transitioning elements blowing out the layout, but also as soon as they're done animating in I can remove the style and they'll revert to their original css.

from react-router-transition.

akeelm avatar akeelm commented on June 7, 2024

I had issues with this too, but even with some of the workarounds here, couldn't get it working properly.

So here's my amendment to one of the workarounds. Notice I do the switch to absolute positioning just before the div disappears.

<RouteTransition
    pathname={this.props.location.pathname}
    atEnter={{ opacity: 0 }}
    atLeave={{ opacity: 0 }}
    atActive={{ opacity: 1 }}
    mapStyles={(styles) => {
      return {
        position: (styles.opacity > 0.3) ? 'relative': 'absolute',
        boxSizing: 'border-box',
        width: '100%',
        height: '100%',
        opacity: styles.opacity,
        transform: 'translateX(' + styles.offset + '%) scale(' + styles.scale + ')'
      }
    }}
  >

from react-router-transition.

jaybe78 avatar jaybe78 commented on June 7, 2024

Hello,

@akeelm The fade effect works quite well with your code. However do you think we could achieve the same for slide effect without absolute positionning ?

from react-router-transition.

uxlayouts avatar uxlayouts commented on June 7, 2024

It would be so helpful to have a codepen example for some of these. I've switched from easy-transition to react-motion to react-router-transition but transitionX fails for all of them. I know this can be fixed. Has someone tried setting the height of the children components\pages with JS or using a css property that does not require position:absolute?

from react-router-transition.

markusv avatar markusv commented on June 7, 2024

I have tried @JurJean solution works great. Except for when switching route back before the first animation is done. Then you have both elements having position absolute, which means the container collapses until the animations are done. Any solution for this?

from react-router-transition.

Xerios avatar Xerios commented on June 7, 2024

For those looking for an answer to this problem, look no further!
I have found a solution of making the transitions overlap without using position:absolute or floats.

How did I do it?
Simple, use CSS Grid on the parent, then have both of the childs use the same grid-area.
This will make both of the elements use the same area, allowing them to overlap while keeping the layout completely functional as before.

The only drawback is IE and it's partial support for CSS Grids, but if you live in the present like most of us then it shouldn't be a big of an issue. Otherwise, you can simply disable the transition for the unsupported browsers.

from react-router-transition.

RomainLanz avatar RomainLanz commented on June 7, 2024

Hey @Xerios 👋

Could you share some code with your solution?

On my project I'm using flexbox everywhere and I have some sort of "jumping" when I use @aakarim solution.

from react-router-transition.

markusv avatar markusv commented on June 7, 2024

good idea. I am now using grid if support. I check for grid with css feature detection and fallback to position absolute/relative if not supported. Thanks

from react-router-transition.

sazedulhaque avatar sazedulhaque commented on June 7, 2024

Thanks @akeelm For the solution.
I face slightly different type of problem my Carousel was not working and after applying your following code

mapStyles={(styles) => { return { position: (styles.opacity > 0.3) ? 'relative': 'absolute', boxSizing: 'border-box', width: '100%', height: '100%', opacity: styles.opacity, transform: 'translateX(' + styles.offset + '%) scale(' + styles.scale + ')' } }}

from react-router-transition.

ueeieiie avatar ueeieiie commented on June 7, 2024

here's a very simple example to get the basics

https://github.com/ueeieiie/simple-route-transitions

from react-router-transition.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.