5
votes

I am using aurelia-animator-css to animate router views. Upon navigation to a new router view, I want the current view to slide off screen to the left while the new view slides onto the screen from the right.

Here is my router-view element:

<router-view swap-order="with"></router-view>

Here is the top element in each of the views:

<div class="pages au-animate">

And here is the css:

@keyframes slideLeftIn {
  0% {
    transform: translate(100%, 0);
  }
  100% {
    transform: translate(0, 0);
  }
}
@keyframes slideLeftOut {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(-100%, 0);
  }
}
.pages.au-enter {
  transform: translate(100%, 0);
}
.pages.au-enter-active {
  animation: slideLeftIn 0.6s;
}
.pages.au-leave-active {
  animation: slideLeftOut 0.6s;
}

I am using autoprefixer, so there is no need for prefixes such as "webkit-".

With swap-order="with", the current view slides off screen to the left, and then the new view appears without sliding.

The same thing happens with swap-order="before".

Here's a youtube screen video with swap-order="with".

With swap-order="after", the current view slides off screen to the left, and then the new view slides in from the right.

Here's a youtube screen video with swap-order="after".

I would think that swap-order="with" would be the one that is needed in this situation. But swap-order="after" is closest to what I need, since both views actually perform slides, just not together.

2
I changed the .pages.au-enter-active animation duration from 0.6s to 1.6s just to see what happens with swap-order="with". It shows the new view sliding in from the right only after the current view is completely off screen. The new view is partially shown at first and then it slides on in as expected. So it seems that the new view is invisible until the current view is removed from the DOM. So now I'm thinking the issue has something to do with my css, but I'm not sure what it might be. Any suggestions? - Jeff G
Tried out a simple project and it works properly, so I'm pretty sure it has something to do with the other css for .pages. - Jeff G

2 Answers

1
votes

Note: This is not an answer to the question, but more an addition to the animation style and question from @powerbouy in the accepted answer.

If anyone came here, as I did, looking for a way to have a phone style navigation:

You would need two more animations, which inverts the direction.

@keyframes slideRightIn {
  0% {
    transform: translate(-100%, 0);
  }
  100% {
    transform: translate(0, 0);
  }
}
@keyframes slideRightOut {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(100%, 0);
  }
}

Then you would need a new set of animation classes:

.slide-right .pages.au-enter {
  transform: translate(-100%, 0);
}
.slide-right .pages.au-enter-active {
  animation: slideRightIn 0.4s;
}
.slide-right .pages.au-leave-active {
  animation: slideRightOut 0.4s;
}

To use the left to right backwards navigation style, you would need to apply the slide-right class to your an parent element of .pages

You could attach it on the router-view element in a back() method like:

  back() {
        document.querySelector('router-view').classList.add('slide-right');
        window.history.back(-1);
  }

Then on the detach() event, you remove it.

detached() {
    // remove class after animation. Only opt-in for showing "back" style animation.
    document.querySelector('router-view').classList.remove('slide-right');
}

UPDATE:

To also detect use of the browsers back button, you could tap into the popstate event. The PLATFORM object comes from the Aurelia PAL package.

Add an eventhandler:

backEventHandler = () => { this.back(true); };

Add event listener when component is attached:

attached() {
        PLATFORM.global.addEventListener("popstate", this.backEventHandler);
    }

Remove event listener when component is detached:

detached() {
        // remove class after animation. Only opt-in for showing "back" style animation.
        document.querySelector('router-view').classList.remove('slide-right');

        PLATFORM.global.removeEventListener("popstate", this.backEventHandler);
    }

Update the back() function to also include a parameter to tell if it's called from the browser or not.

back(native?: boolean) {
        document.querySelector('router-view').classList.add('slide-right');

        if (!native) {
            window.history.back(-1);
        }
    }
0
votes

It turns out that I just needed to add the following styles to my .pages class:

.pages {
    position: absolute;
    left: 0px;
    top: $navBarHeight; /* using sass var for the height of my navbar */
}

Now everything works as expected.