Hi, Is it possible to check to and from inside a transition object? I want to use different transitions depending on where the user came from and are going.
What is the suggested way of doing this? Can I keep all my transitions in some folder and export/import them, using the transition function to check which one to use?
This is a transition i'm using inside one of my page components:
transition: {
mode: 'out-in',
css: false,
enter (el, done) {
let tl = new TimelineMax
let SplitLines = new SplitText('.js-lines', {type: "words" })
let lines = SplitLines.words
TweenMax.set('.js-lines', { perspective: 800 })
function kill () {
SplitLines.revert()
done()
}
tl.staggerFrom(lines, 1.5, {
opacity: 0,
yPercent: 50,
scale: 0.85,
rotationX: -90,
transformOrigin: "center bottom",
ease: Expo.easeOut
}, 0.075, "+=0", kill)
},
leave (el, done) {
TweenMax.to(el, 0.5, { autoAlpha: 0, onComplete: done })
}
}
Would something like this be possible?
export const fromPageOne = {
mode: 'out-in',
css: false,
enter () {
console.log('from page one')
done()
}
}
export const fromPageTwo = {
mode: 'out-in',
css: false,
enter () {
console.log('from page two')
done()
}
}
export const toPagOne = {
mode: 'out-in',
css: false,
leave () {
console.log('to page one')
done()
}
}
export const toPageTwo = {
mode: 'out-in',
css: false,
leave () {
console.log('to page two')
done()
}
}
then in the page component:
transition (to, from) {
return from.name == 'index' ? fromPageOne : fromPageTwo
return to.name == 'index' ? toPageOne : toPageTwo
}
Hi @jesperlandberg!
Is the issue that you'd like to reuse some of the animation? You could use a mixin for this- you would have to still designate that transition per page, though. You could also use Vuex to coordinate per template, but you miss out on the js hook per page, so leave is a bit more difficult, as well as designating the transition mode to out-in, which it looks like you're going to need. If they are just entrances, it would work on a mounted() hook.
Also, I noticed you're not passing the done as a param, and you're not calling TimelineMax as a function as a first example. Ideally, you would do something like let tl = new TimelineMax({onComplete:done}), that plays with the timeline in the most clean way I've found due to the way the ordering is executed :)
One more thing: it might be good to make use of clearProps (this is a GSAP thing) in a TweenMax.set inside the page on a beforeEnter if you're going to do reuse them because if they're out of order you might have transformOrigin applied and it will screw with the coordination from different locations.
Hope that helps!
p.s. I have some reference material for mixins and coordinating page transitions as well, if you'd like to look at some examples.
Hi @sdras !
Not really reuse, more like having completely different transitions depending on what route ur going to, and what route you came from. Basically like (pseudocode) :
if (from /about)
return someEnterTransition
else
return defaultEnterTransition
and:
if (to /about)
return someLeaveTransition
else
return defaultLeaveTransition
Would be awesome if u could give me a look at examples for coordinating page transitions using mixins (or whatever is the recommended way) =)
Ah, yeah! That's actually much easier then, you don't even need a mixin.
I do this here in this example:
https://github.com/sdras/nuxt-type
Each page has it's own transitions (it's own enter and leave). I'm using GSAP and splitText too, so it will actually be a nice 1:1 for what you're trying to accomplish.
Here's a live example: http://nuxt-type.now.sh/ You can see all the h1s and mountains come in and leave a little differently per page. I also wrote a post/tutorial on this, but I think you're farther along in understanding than the post can help with. Just in case, here it is.
Btw, there's a bug in the current version of nuxt for transitions that they're actively working on at this time, so if you can hold off until next week's release, it will probably be smoother sailing. That should give you everything you need, but feel free to open an issue on my repo if anything is unclear :)
thanks @sdras , the nuxt-type demo is real nice! I might been a little unclear tho, english isn't my main language so sometimes it can be hard to explain things=). What I mean is that except for different pages having unique transitions, I also need some of the pages to have multiple transitions, and the to and from routes decide which one should be used. Like, if u go to the about-page from the home-page, I want to use transition1 when entering the about-page, however if i come from a project-page, I want the about-page to use transition2.
I remember back before in Vue v1, I checked to and from to in some deprecated vue-router life cycle hooks.
Oh I see! Sorry for the confusion here.
So, I'm in the middle of creating a proof of concept for this myself actually! (waiting on that release to keep going)- here's what my plan is: number the pages, use Vuex to hold the state of what page it is, and as pages change, update the current page. Then use conditionals as you stated (I would probably still have them work per page, and then nest the conditionals within the entrance and leave, but YMMV).
I do it that way because I also want to coordinate in the parent, in layouts/default, because I want to change the menu as well. This way I'm leveraging Vuex to coordinate animations application-wide (I could also theoretically animate nested components this way as well)
If you can think of a better way, by all means! But that's where I'm headed to work this out.
@sdras sounds like a smart way to handle it. Will try something similar myself. Looking forward to seeing ur solution, because u will share it huh?=) Your vue/nuxt tutorials are probs some of the best out there.
Absolutely! I'm making it for the community. And thanks!
@sdras Experimented anything with this yet?=) I'm currently setting "currentPage" and "nextPage" in the store.
@jesperlandberg how/where are you setting the to/from in the store?
My brain is starting to fry solving this
@chasebank well i'm not, had some issues with my solution, so still looking for another one. Can it really be this hard to archieve?
@chasebank so I think I solved this for now, at least it is fitting my needs. Sure someone will come up with something better.
What I do is that I set two store states called "toPage" and "fromPage" when a link to another page is clicked, and then I check the values of these in my transition and execute the correct animation (gsap) code based on it.
Basically:
Mixin:
import { mapMutations, mapGetters } from 'vuex'
export const fromToPageHandler = {
computed: {
...mapGetters([
'getFromPage',
'getToPage'
])
},
methods: {
...mapMutations([
'setFromPage',
'setToPage'
])
}
}
Link:
<template>
<nuxt-link to="/somePage" @click.native="setFromToPages(from, to)">link</nuxt-link>
</template>
<script>
import { fromToPageHandler } from '~/mixins/fromToPageHandler'
export default {
mixins: [
fromToPageHandler
],
methods: {
setFromToPages (from, to) {
this.setFromPage(from)
this.setToPage(to)
}
}
}
</script>
And then inside my transition basically:
if ((this.$store.state.fromPage == 'something' ) && (this.$store.state.toPage == 'something')) {
... execute ...
} else ...
@jesperlandberg thanks for the guidance! I tried taking a crack at this two days ago, but I was having trouble importing anything from data/ computed and assumed I'd have the same issue with Vuex. Just tested my own solution and everything works perfectly using just vuex. Thanks again for posting your solution.
@jesperlandberg @abattenburg
So, I've revisited this issue... I actually abandoned Nuxt over this (and a few other things) that made me feel the cons of Nuxt were outweighing the pros. But... Now I'm back!
Seems to me the basic idea is we need some way to
The hardest part for me has been finding a way to access page values in router events. There's likely many ways of doing this but the crux is this is normally super simple in Vue. Just set a meta prop on the route. But in Nuxt the idea of "meta" seems very convoluted, and I still haven't figured out a way to set true 'route' meta.
But you can look at 'normal' meta inside middleware, and middleware can also connect with router events.
middleware/routeTransition.js
export default function ({ store, route, redirect }) {
const routeDepth = route.meta.map((meta) => {
if (meta.depth && typeof meta.depth !== 'undefined')
return meta.depth
return 0
})
// send depth to the store
store.commit('setRouteTransitionDirection', routeDepth)
}
nuxt.config.js
module.exports = {
...
router: {
middleware: 'routeTransition'
},
}
store/index.js
import Vuex from 'vuex'
const createStore = () => {
return new Vuex.Store({
state: {
routeDepth: '1',
routeTransitionDirection: 'right'
},
mutations: {
setRouteTransitionDirection(state, newRouteDepth) {
newRouteDepth < state.routeDepth ? state.routeTransitionDirection = 'left' : state.routeTransitionDirection = 'right'
state.routeDepth = newRouteDepth
}
}
})
}
export default createStore
inside any page
<script>
export default {
meta: {
depth: 3
}
}
</script>
Now, what you do with that depends on how you're handling transitions.
Another unfortunate issue with Nuxt is we can't access the store from the config, where the default page transition is set.
Personally I've found many issues with the implementation of layout transitions, so I just don't use them. Which then creates conflicts with page transitions, so I really don't even use layouts. I treat the default layout as if it were App.vue which means I can treat the <nuxt/> element as if it were <router-view> (which we normally wouldn't have access to in Nuxt).
So I wrap that in a transition and bind it's name to that vuex property
<template>
<div id="layout">
<transition :name="routeTransitionDirection">
<nuxt :key="$route.fullPath" />
</transition>
</div>
</template>
There's a few other options I've played with. Maybe I'll write a blog post. But, generally I think this use of middleware is a solid approach. It lets you 'set it and forget it' and not have to import anything extra into our pages. Just set a meta property and move on, and then handle the rest in middleware or vuex.
This doesn't exactly solve the issue, but it's one possible solution. In this blog post I go over how to create different animations per page. https://css-tricks.com/native-like-animations-for-page-transitions-on-the-web/
And this site shows it in action: https://page-transitions.com/
We're using transitions because they are declaratively describing the motion, whatever we desire it as, and the page hooks hold the state of the element.
I know that's not exactly what you asked but dropping it in, in the chance that it's helpful. Cheers!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
@jesperlandberg @abattenburg
So, I've revisited this issue... I actually abandoned Nuxt over this (and a few other things) that made me feel the cons of Nuxt were outweighing the pros. But... Now I'm back!
Seems to me the basic idea is we need some way to
The hardest part for me has been finding a way to access page values in router events. There's likely many ways of doing this but the crux is this is normally super simple in Vue. Just set a meta prop on the route. But in Nuxt the idea of "meta" seems very convoluted, and I still haven't figured out a way to set true 'route' meta.
But you can look at 'normal' meta inside middleware, and middleware can also connect with router events.
middleware/routeTransition.js
nuxt.config.js
store/index.js
inside any page
Now, what you do with that depends on how you're handling transitions.
Another unfortunate issue with Nuxt is we can't access the store from the config, where the default page transition is set.
Personally I've found many issues with the implementation of layout transitions, so I just don't use them. Which then creates conflicts with page transitions, so I really don't even use layouts. I treat the default layout as if it were
App.vuewhich means I can treat the<nuxt/>element as if it were<router-view>(which we normally wouldn't have access to in Nuxt).So I wrap that in a transition and bind it's name to that vuex property
There's a few other options I've played with. Maybe I'll write a blog post. But, generally I think this use of middleware is a solid approach. It lets you 'set it and forget it' and not have to import anything extra into our pages. Just set a meta property and move on, and then handle the rest in middleware or vuex.