javascriptsveltesvelte-3svelte-transition

Svelte transition defined per transition and not per component


I'm developing a Svelte UI with full page navigation using svelte-spa-router. I'm facing the case where the UX designer defined the transition between page "per transition" and not per page has it's meant to be in Svelte (AFAIK).

enter image description here

E.g. in this UX page B1 out transition would :

The UX actually makes sense because B1/B2, C1/C2 are similar but treats the same subject from a different point of view.

Svelte transition are working great but are defined per component, with a in transition and an out transition.

I tried leveraging the fact that transition property could be object and reactive.

<script>
    import { fade } from "svelte/transition";
    let page = "A";
    let duration = 0;
    function goto(dest) {
        if(dest == "A" || page == "A") {
            duration = 0;
        } else {
            duration = 400;
        }
        page = dest;
    }
</script>

{#if page == "A"}
    <section class="A" transition:fade={{duration: duration}}>
        <h1>Page A</h1>
        <nav on:click={e => goto("B1")}>Goto B1</nav>
        <nav on:click={e => goto("B2")}>Goto B2</nav>
    </section>
{:else if page == "B1"}  
    <section class="B1" transition:fade={{duration: duration}}>
        <h1>Page B1</h1>
        <nav on:click={e => goto("A")}>Goto Back</nav>
        <nav on:click={e => goto("B2")}>Goto B2</nav>
    </section>
{:else if page == "B2"}
    <section class="B2" transition:fade={{duration: duration}}>
        <h1>Page B2</h1>
        <nav on:click={e => goto("A")}>Goto Back</nav>
        <nav on:click={e => goto("B1")}>Goto B1</nav>
    </section>
{/if}

<style>
    section {
        position: absolute;
        width: 500px;
        height: 500px;
    }
    section.A {
        background: pink;
    }
    section.B1 {
        background: blue;
    }
    section.B2 {
        background: yellow;
    }
</style>

But I cannot figure out how to change the transition effect (maybe a custom transition function ?). Moreover, this solution seems very complicated, time consuming and could really turn to a ball of spaghetti in a more complex UX.

In addition, in svelte-spa-router I did not found a way to know where I'm coming from (i.e. the prevision location) to manage the transition accordingly.

Any thoughts ?


Solution

  • The in: syntax accepts javascript functions, things like fade are regular javascript functions this allows for switching.

    // pageTransion.js
    function slidePage(el) {
      return fly(el, { x: 200, duration: 300 });
    }
    function disolvePage(el) {
      return fade(el, { duration: 300 });
    }
    let previous = "";
    let current = "";
    export function setNextPage(next) {
      previous = current;
      current = next;
    }
    
    export function pageTransition(el) {
      const transitions = {
        "b1-b2": disolvePage,
        "b1-c1": slidePage,
        // etc
      };
      return transitions[previous + "-" + current];
    }
    
    
    // b1.svelte
    <div transition:pageTransition>
    
    

    You'll need to call the setNextPage before activating the page.

    svelte-spa-router doesn't expose the previous url, but you could listen to the onhashchange event and store the url history yourself. ( ordering is important, you can use the capture phase to run before the the spa-router code.)