YouTubeのようなページ読み込みアニメーションをSveletkitで加えてください


我々はみなそれを見た.現代のウェブサイトでページ読み込みを示すトップの色のスライバ.YouTubeはこの素晴らしい例です.nextjsや他のフレームワークを使ってこれを行うライブラリがあるかもしれませんが、SveletKitにはまだありません.しかし、幸いにも、それは自分自身を実装するのは難しいことではない!あなたがコードだけに興味があるならば、ここにありますGitHub repository .

導入


こんにちは!ようこそ私の最初のブログの投稿までの開発者(実際には誰でも).あなたがまだ我々がするつもりの明確な絵を持っていないならば、あなたのためのGIFはここにあります:

あなたはclick here デモにも.SveletKitでは、あなたはload ページがロードされる前に、サーバー/クライアントで実行される関数.Load関数はその仕事をしていますが、上のページローディングバーは素敵なビジュアルフィードバックのために増加し続けます.それは素晴らしいです!

ハウ


いくつかのコードを書くためにダウンする前に、すぐにどのように動作するかを説明しましょう.私は、あなたにSvelte、Svelteの店とSveletkitで少なくともいくつかの経験があると仮定します.
私たちはPageLoader.svelte コンポーネント.これは、マウントされた時間(ユーザーがリンクをクリックするとき)です.幅は0から70 %になり始める.とすぐに次のページが読み込まれるとすぐに、それはすぐに100 %にアニメーション化されますし、きれいに消える.私たちはいつナビゲーションが開始され、Sveletkitsveltekit:navigation-start and sveltekit:navigation-end ウィンドウイベント.我々は、このナビゲーション状態データをsveltewritable 私たちがコントロールできるようにPageLoader.svelte コンポーネントのアニメーション.
それはそれです!これは十分に簡単に聞こえる場合は、先に行くと、これを試してみる!

セットアップ


あなたはおそらくあなたの既存のプロジェクトでこれを行うでしょう.しかし、このチュートリアルのために、新しいSvelteKitプロジェクトを足場に入れさせてくださいnpm init svelte@next . この例では、typescriptを有効にします.必要なパッケージのインストール後npm install , 私はいくつかのファイルを作成します.以下にディレクトリ構造を示します:
src
└───routes
|   |   __layout.svelte
|   |   page-1.svelte
|   |   page-2.svelte
|   |   index.svelte
|   |
└───components
|   |   PageLoader.svelte
|   |
└───stores
|   |   navigationState.ts
|   |
└───styles
|   |   global.css

かなり簡単、右?スタイリングを加えますglobal.css ファイル.私はSvelteのコンポーネントでそれを行うことができますが、これは、ページ間で共有スタイルを持つ小さなプロジェクトです.このチュートリアルのGithubリポジトリを参照すると、コードが必要になります.
今ではページを作成する時間です.リンクしますpage-1.svelte and page-2.svelte 内部のアンカータグの使用index.svelte . 次の3つのコードです.
<!-- routes/index.svelte -->

<div class="container">
    <div class="content">
        <h1>Page loading progress bar in action with SvelteKit.</h1>

        <div class="links">
            <a href="/page-1">Page 1</a>
            <a href="/page-2">Page 2</a>
        </div>
    </div>
</div>
<!-- routes/page-1.svelte -->

<div class="container">
    <div class="content">
        <h1>You're on Page 1.</h1>
        <div class="links">
            <a href="/">Home</a>
            <a href="/page-2">Page 2</a>
        </div>
    </div>
</div>
<!-- routes/page-2.svelte -->

<div class="container">
    <div class="content">
        <h1>You're on Page 2.</h1>
        <div class="links">
            <a href="/">Home</a>
            <a href="/page-1">Page 1</a>
        </div>
    </div>
</div>
あまりにも空想.それでは、実際に関連するコードに移りましょう.

これをしましょう


私たちはroutes/__layout.svelte ファイル.すべてのページは、このレイアウトファイル内でレンダリングされますので、他のページに場所があるようにスロットを追加する必要があります.また、インポートしますglobal.css はい.
<!-- routes/__layout.svelte -->

<script lang="ts">
  import '../styles/global.css';
</script>

<slot></slot>
この時点で実行することができますnpm run dev すべてが正常に動作しているかどうかを確認します.
Svelteという特殊元素<svelte:window> . ウィンドウのイベントリスナーをこの要素で簡単に追加できます.docsを検査するとき、私はsveltekitエイドを知って来ましたsveltekit:navigation-start and sveltekit-navigation-end ウィンドウイベント.彼らをつかまえましょう.
<!-- routes/__layout.svelte -->

<script lang="ts">
    import '../styles/global.css';
</script>

<svelte:window
    on:sveltekit:navigation-start={() => {
        console.log('Navigation started!');
    }}
    on:sveltekit:navigation-end={() => {
        console.log('Navigation ended!');
    }}
/>

<slot></slot>
今すぐブラウザのコンソールを開き、ナビゲーションメッセージを正しく取得するかどうかを確認します.私の側のすべてはよいので、行きましょうstores/navigationState.ts ファイル.
// stores/navigationState.ts

import { writable } from 'svelte/store';

type NavigationState = "loading" | "loaded" | null;

export default writable<NavigationState>(null);
今、我々はどこのアプリの中からナビゲーションの状態を知る方法があります.我々はまだこれのためにイベントリスナーを編集しませんでした、しかし、我々はそれに着きます.
何かをする前にcomponents/PageLoader.svelte コンポーネント.最初にマークアップを書きましょう.
<!-- components/PageLoader.svelte -->

<div class="progress-bar">
    <div class="progress-sliver" style={`--width: ${$progress * 100}%`} />
</div>

<style>
    .progress-bar {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        height: 0.5rem;
    }
    .progress-sliver {
        width: var(--width);
        background-color: #f8485e;
        height: 100%;
    }
</style>
ご覧の通り、我々はAで通ります$progress * 100 スタイル属性を持つCSSカスタムプロパティに変数.progress スベートになるtweened 値.
当初progress は0になり、コンポーネントがマウントされるとすぐに、0.7 %まで70 %に移動します.また、私たちはnavigationState 以前に作成した店からの変更.状態が'loaded' , 進捗を1(100 %)に設定します.フルコード:
<!-- components/PageLoader.svelte -->

<script>
    import { onDestroy, onMount } from 'svelte';
    import { tweened } from 'svelte/motion';
    import { cubicOut } from 'svelte/easing';
    import navigationState from '../stores/navigationState';

    const progress = tweened(0, {
        duration: 3500,
        easing: cubicOut
    });
    const unsubscribe = navigationState.subscribe((state) => {
        if (state === 'loaded') {
            progress.set(1, { duration: 1000 });
        }
    });
    onMount(() => {
        progress.set(0.7);
    });
    onDestroy(() => {
        unsubscribe();
    });
</script>


<div class="progress-bar">
    <div class="progress-sliver" style={`--width: ${$progress * 100}%`} />
</div>

<style>
    .progress-bar {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        height: 0.5rem;
    }
    .progress-sliver {
        width: var(--width);
        background-color: #f8485e;
        height: 100%;
    }
</style>
ご存知のように、コンポーネントが破壊されたとき、私たちはストアを取り消すことを忘れませんでした.また、期間に注意してください.我々が0から70 %まで動き出しているとき、我々は少し遅くなります.ページが読み込まれると、我々ははるかに速く100 %に行きます.
現在、1つだけ残っていることがあります.レッツゴートゥバックroutes/__layout.svelte ファイル.イベントリスナーを変更して、navigationState ときにナビゲーションが発生します.我々は、輸入するつもりですPageLoader.svelte ここでコンポーネントを表示し、navigationState'loading' . ページがロードされると、PeleloaderコンポーネントをフェードアウトするためにSvelteのフェード遷移をもたらすでしょう.しかし、覚えて、我々はそれが消えて前に進捗バーが100 %に達するようにいくつかの遅延を追加する必要があります.コードを見てみましょう.
<!-- routes/__layout.svelte -->

<script lang="ts">
    import { fade } from 'svelte/transition';

    import navigationState from '../stores/navigationState';
    import PageLoader from '../components/PageLoader.svelte';
    import '../styles/global.css';
</script>

<svelte:window
    on:sveltekit:navigation-start={() => {
        $navigationState = 'loading';
    }}
    on:sveltekit:navigation-end={() => {
        $navigationState = 'loaded';
    }}
/>
{#if $navigationState === 'loading'}
    <div out:fade={{ delay: 500 }}>
        <PageLoader />
    </div>
{/if}

<slot />

それは、人々!


あなたのページ読み込みアニメーションが準備ができました.devサーバーを再起動し、正常に動作するかどうかを確認します.

結論


私の最初のポストまで、私はそれがよかったことを望む!チェックアウトGitHub repository あなたがまだ疑問を持つならば.これは最善の方法ではないかもしれませんが、ほとんどの場合はうまくいきます.お気軽にフィードバック/コメント/質問を残して.