【Sass】【Javascript】CSSアニメーションとローディング画面【おまけのRails】

ポートフォリオにローディングアニメーションを実装をしたので、備忘録をつらつらと。

#Sassでアニメーション
CSSをもっと便利に使えるSassを使って、簡単なアニメーションをコーディングしました。

以下がデモ動画。
<blockquote class="twitter-tweet" data-theme="dark"><p lang="ja" dir="ltr">Sassを使ってこんな感じのローディングアニメーション作りました〜。<br><br>ポートフォリオにも実装完了！ <a href="https://t.co/0LAQzVcxzh">pic.twitter.com/0LAQzVcxzh</a></p>&mdash; hukushima (@hukushima_nem) <a href="https://twitter.com/hukushima_nem/status/1243171224034758656?ref_src=twsrc%5Etfw">March 26, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

こんな感じで、ローディング中にノートに記述してる的なアニメーションを作ります。

サンプルコード
https://github.com/soehina/load_sample

##まずは土台から
とりあえず形だけ作ってみましょう。

```index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div id="back">
        <div>
            <div id="load-box">
                <div></div>
                <div></div>
                <div></div>
                <div></div>
                <div></div>
                <div></div>
                <div></div>
            </div>
            <p>Loading<span>...</span></p>
        </div>
    </div>
</body>
</html>
```
```style.scss
#back{
    /* 画面いっぱい */
    width: 100vw;
    height: 100vh;
    background-color: #ffffff;
    display: flex;
    & div{
        display: flex;
        justify-content: center;
        flex-direction: column;
        align-items: center;
        margin: auto;
        & p{
            color: #a9dee6;
            }
        }
    }

#load-box{
    width: 100px;
    height: 135px;
    border: 1px solid #a9dee6;
    & div{
        width: 60px;
        border: 1px solid #a9dee6;
        margin: 5px auto;
    }
}
```

divでいくつか箱を作っています。
id="back"はローディング画面全体の箱を指します。

Sassは入れ子構造でCSSを記述できるのでスッキリしてて良いですね。

とりあえずこれで形ができました。

##アニメーションをつける
ではアニメーションを付与しましょう。

@mixinを使用すればcssをメソッドのように扱えてメンテナンスが楽になります。
なので、外部ファイル_mixinを作り、今回付与するアニメーションの定義をします。

```_mixin.scss
@mixin animation(
    $name,
    $duration: 3s,
    $interation-count: infinite,
    $fill-mode: forwards
){
    animation: {
        name: $name;
        duration: $duration;
        iteration-count: $interation-count;
        fill-mode: $fill-mode;
    }
}
```
引数に使いたいアニメーションを色々初期設定してます。
そして各アニメーションにその引数を渡してあげます。
これ本当便利ですね。

それぞれの機能についてはこちらの記事でわかりやすくまとめてくれています。
これは保存版です。
[【CSS3】@keyframes と animation 関連のまとめ](https://qiita.com/7968/items/1d999354e00db53bcbd8)

ではこのmixinを用いて、style.scssを以下のように変えてあげましょう。

```style.scss
@import "mixin";

#back{
    width: 100vw;
    height: 100vh;
    background-color: #ffffff;
    display: flex;
    & div{
        display: flex;
        justify-content: center;
        flex-direction: column;
        align-items: center;
        margin: auto;
        & p{
            color: #a9dee6;
            /* 追加 */
            & span{
                transform-origin: left;
                @include animation(
                    $name: dot-anime
                );
            }
        }
    }
}

#load-box{
    width: 100px;
    height: 135px;
    border: 1px solid #a9dee6;
    & div{
        width: 60px;
        border: 1px solid #a9dee6;
        margin: 5px auto;
        /* 追加 */
        transform-origin: left;
        animation-timing-function: cubic-bezier(1, 0.03, 0.98, 0.04);
        @include animation(
            $name: load-anime
        );
        /* for文でアニメーションのタイミングをずらす */
        @for $i from 1 through 7 {
            &:nth-child(#{$i}){
                animation-delay: -1.3s + $i * 0.1s;
            }
        }
    }
}

/* 追加 */
@keyframes load-anime{
    0%{
        opacity: 0;
        transform: scaleX(0);
    }
    50%{
        opacity: 1;
        transform: scaleX(1);
    }
    100%{
        opacity: 0;
        transform: scaleX(0);
    }
}

/* 追加 */
@keyframes dot-anime{
    0%{
        opacity: 0;
    }
    50%{
        opacity: 1;
    }
    100%{
        opacity: 0;
    }
}
```

ざっと説明しますと、@includeで先ほどのmixinで定義したアニメーションを読み込んでいます。
外部ファイルで管理してるので、同じような処理もコードが短く済んで良いですね。

また、Sassではfor文が使えるので、子要素に対してタイミングをズラして動くアニメーションを付与してあげました。

@keyframesでは、animation-nameに対してアニメーションを付与してます。
0%と100%はそれぞれアニメーションのはじめと終わりを指しているので、好きなタイミングで好きなアニメーションを付与してあげましょう。

#Javascriptでローディング
アニメーションができたので、Javascriptでローディングの設定をしましょう。
と言ってもこちらはそんなに難しくありません。
以下のように記述するだけです。

```application.js
function loaded(){
    const loading = document.querySelector('#back');
    loading.classList.add('loaded');
}
window.onload = loaded;
```
関数loadedには次のような処理をさせています。

- ローディング画面全体のhtmlを取得する処理
- そこにローディング画面を隠すloadedクラス（scssに追加します）を付与する処理

この処理を画面読み込みが完了したら発動するように、window.onloadで呼び出します。

あとはscssファイルに必要なスタイルを記述するだけです。

```style.scss
.loaded{
    opacity: 0;
    visibility: hidden;
}
```
これでロードが完了したらローディングアニメーションが隠れます。

##Railsでのちょっとした注意点
今回これらをRailsアプリに実装したのですが、そのままjsファイルに記述すると一生ローディング画面になるという中々だるい展開に。

原因はjsファイルにあらかじめ記述してある、

```application.js
//= require turbolinks
```
みたいです。

同じような感じで困ったら、とりあえずこいつを消してやりましょう。

#まとめ
SassとJavascriptを使ってローディング画面を実装しました。
フロントの勉強にはとても良かったです。

ローディング画面があるだけで良い感じのアプリに見えるので、もし実装を考えていたら参考にしてください。

ではでは。