Skip to content
This repository has been archived by the owner on Jan 11, 2023. It is now read-only.

Element transitions between pages #778

Closed
buhrmi opened this issue Jun 30, 2019 · 9 comments
Closed

Element transitions between pages #778

buhrmi opened this issue Jun 30, 2019 · 9 comments

Comments

@buhrmi
Copy link

buhrmi commented Jun 30, 2019

Here is an interesting site demonstrating element transitions when navigating between pages. I thought it would be cool if sapper could do something like this natively with the animate directive. So, for example:

index.html:

<div class="something">
  <div id="amazing" animate:flip={{duration: 200, key: 'hello'}}>I'm here</div>
</div>
<style>
#id {
  width: 100px;
  height: 100px;
}
</style>

detail.html:

<div id="amazing" animate:flip={{duration: 200, key: 'hello'}}>Now I'm over here</div>
<style>
#id {
  display: absolute;
  top: 30px;
  width: 200px;
  height: 200px;
}
</style>

And between navigation, sapper would find the element with the same ID or key, and automatically apply a flip animation.

@buhrmi
Copy link
Author

buhrmi commented Jul 1, 2019

To make it work, I guess the sapper router would check if there are any keyed elements inside the current page (and layout) component, see if there are any matching keyed elements on the new page (or layout) component, and then create a FLIP transition between them.

@buhrmi
Copy link
Author

buhrmi commented Jul 1, 2019

Looks like @Rich-Harris already thought of that as "Scenario 3" in this issue sveltejs/svelte#1431 ... But this hasn't been implemented, right?

@buhrmi
Copy link
Author

buhrmi commented Jul 2, 2019

Been working on this a bit. At first I tried to use the built-in crossfade() function, but the problem is that the old page component stays in the page until the animation is completed and the new page component is being appended beneath it.
pageflip

So I started to work on a new custom animation, that functions similar to crossfade(), but with the duration of the out-animation set to 0. The way I wanted it to work is:

  1. Out-transition is called. The duration is 0, so all it does is store the clientRect of the "sending" element.
  2. The old page component is removed from the DOM and the new component is rendered
  3. The In-transition is called, calculating the position delta and play the FLIP animation.

However, the problem that I can't get around, is that sapper does not remove the old page component before calling the In-transition function. That means that the clientrect.top that is used to calculate the FLIP animation is not correct. Now I wonder if there is a way to modify sapper to not call the in-transition before removing the old page component (if it doesn't have an animation with a duration > 0).

@buhrmi
Copy link
Author

buhrmi commented Jul 2, 2019

Progress 😄 Have to change Svelte internals a little bit to get it working. Still some bugs but I'll figure it out and make a PR

ezgif-1-3b42140b2353

@buhrmi
Copy link
Author

buhrmi commented Jul 3, 2019

Getting there
rkO24Wit7J

@buhrmi
Copy link
Author

buhrmi commented Jul 4, 2019

Okay, I figured it out how to do this without modifying the Svelte source code except for a tiny tweak: sveltejs/svelte#3175

updated my blog post, too: https://dev.to/buhrmi/svelte-component-transitions-5ie

@rchrdnsh
Copy link

hmmmm...sorry if my question is simple but how can I do a simple fade-out-and-in between two routes in sapper?

I’m Vie there is a simple wrapper component, and that’s it. Haven’t figured it out in svelte/sapper yet, however.

@buhrmi
Copy link
Author

buhrmi commented Sep 19, 2019

@rchrdnsh you could wrap your page in <div transition:fade style="position:absolute">...</div>

clozach added a commit to clozach/everyoneventures that referenced this issue Oct 22, 2019
…e titles and images when transitioning routes.

The biggest sticking point was that I wanted to be able to (for this first pass), keep the word "Ouroboros" on-screen when transitioning back-and-forth between the "projects" page and `routes/ouroboros/index.svelte`. The key seems to be making sure that every component involved in animations gets its _entire_ contents wrapped in a `div.route-animation-container`. Maybe this is why @buhrmi chose <main> as the place to hook `position:absolute` in the example I used to work this out: sveltejs/sapper#778

Should I follow suit? TBD.
@finkrer
Copy link

finkrer commented Jan 2, 2021

@buhrmi So how did you solve the old page not being removed? I can see that the code from your post works, but when I try to add animations myself that same issue arises. If I am to build my own site with this, I'd rather not depend on some unknown magic in your code, haha.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants