JS スクロールすると要素がフワッと出現する方法

最初は見えない状態から、ブラウザをスクロールすると
![スクリーンショット 2022-04-05 1.04.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521240/48e3fcc0-1792-2532-c6b5-1a9efe90b01a.png)
画像のように要素が下から上へ少しだけ動きながらフワッとフェードインする方法をやっていきます。

_HTMLコード_
```
<body>
  <header>
    <h1>タゴ'sクリエイト</h1>
    <nav>
      <p>Global-Navigation</p>
    </nav>
  </header>
  <main>
    <div class="scrollA scrollUp">
      <h2>Content</h2>
    </div>
    <div>
　　　　　　　　　　　　・
　　　　　　　　　　　　・
　　　　　　　　　　　　・
　　　　　　　　　　　　・
  </main>
  <script src="example.js"></script>
</body>
```
![スクリーンショット 2022-04-05 1.11.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521240/882cd328-763b-0625-eb82-a23f23b57f40.png)
まずこの様なものを表示させます。
この黄色の「Content」部分に対して、「Content」の下辺が画面の下辺より上にいくと、
元々消しておいた「Content」が下から上にフワッとフェードインするものを作っていきます。

_JSコード_
```
window.addEventListener('load',fadeCheck);  //１
window.addEventListener('scroll',fadeCheck,{passive:true}); //２
function fadeCheck(){  //３
  var cont=document.querySelector('.scrollA');  //４
  if(window.innerHeight>cont.getBoundingClientRect().bottom){ //５
    cont.classList.add('fadeJS'); //６
  }
}
```

_CSSコード_
```
.scrollA{
  opacity: 0;
}

.scrollUp{
  transform: translate(0,50px);
}

.fadeJS{
  opacity: 1;
  transform: none;
  transition: all 2s ease;
}
```
今回は「mane」要素の中にある、一番最初の「div」要素にのみフェードインを適用させるコードです。
では上から順に説明です。

JSコード
１、まず「addEventListener」で、ウィンドウをロードした時に「fadeCheck」関数を呼び出します。（この「fadeCheck」は後で説明しますが、大まかに言うと「HTMLの要素にclassを追加するか判定」という意味です）
２、また「addEventListener」を使い、ウィンドウをスクロールした時にも「fadeCheck」関数を呼び出します。

ここで第三引数に「{passive:true}」を入れていることの説明を簡単にします。
「スクロールジャンク」と呼ばれる、主にモバイル端末で起きる、スクロールの際JSの処理待ちのためのカクカクする現象があり、
これは「PreventDefault」という処理を中断して他の処理をさせるメソッドがあるかないかをスクロールのたびにブラウザ側がチェックしているために起こっています。
「addEventListener」の第三引数に「{passive:true}」を入れることで、事前に
このページには「PreventDefault」メソッドがないよ！
と宣言しているということになります。
なので、「{passive:true}」を入れることによって、「スクロールジャンク」を防ぎスムーズにスクロールできるようになるというわけです。

３、次は先ほどの「fadeCheck」関数を記述していきます。
4、まずは「querySelector」でHTMLのコンテンツのクラス名「.scrollA」を要素１つだけ取得、それを変数「cont」に代入します。
５、次にif文を設定、「getBoundingClientRect」により「cont」要素に対し下辺を基準高さとし、「window.innerHeight（ブラウザの表示高さを数値化）」より小さい（画面下部よりさらに上に行き、ブラウザ上に見える状態）の場合という条件式を記述。

ここで「getBoundingClientRect」について説明です。
これは「要素.getBoundingClientRect().X」とすることで、
(今回Xは「bottom」を指定してますが、他の指定種類については後述します)
要素のボックス（border、padding含む）の下辺の座標が、ブラウザの表示部分（ビューポート）の基準点である左上（左上が「0,0」となっている）を基準として、どの位置にいてるかを数値として取得できます。
この「bottom」の他にも「top,left,right」等があり、それぞれボックスの上辺、左辺、右辺を意味します。
例えば「スクロールしてh1要素の上辺が画面上部に設置するとイベントを起こしたい」等の時は、
「top」を使用するといいと言うことですね。

６、条件が当てはまる「cont」要素に「fadeJS」というクラスを付与します。

CSSコード
「scrollA」クラスと「scrollUp」クラスには、まずJSが適用される前の待機状態を記述します。
今回だと「scrollA」の「opacity（不透明度）」を「0」にして見えなくし、
「scrollUp」の「transform」を使用し「translate（要素の位置）」の値を50px下にしています。
そしてJSが適用されて追加されるクラスである「fadeJS」は、
「opacity」を初期値の「100」に戻し、「transform」も初期値の「none」に戻します。
このままではJSが適用されるといきなり「fadeJS」が適用されるため、ただ所定の場所にパッと現れるだけになってしまいます。
なので、「fadeJS」に「transition」を追加し、「all（トランジション対象のCSSプロパティ→全て）」「2s（2秒間かけてアニメーション）」「ease（なめらかに始まりなめらかに終わる）」の3つを記述します。
こうすることで、「scrollA」と「scrollUp」の状態から「fadeJS」の状態に変わる時に、
「transition」の変化を行いながら変わっていってくれるようになります。

これで要素１つに対して、スクロールすると要素がフワッと出現する方法は以上になります。
ですがこのHTMLの表示ページだと大体はコンテンツ全部に対して先ほどまでのアニメーションを適用させたいと思いますので、
ページ内の全てのコンテンツ要素に対してアニメーションをかけていきます。

_HTMLコード_
```
<body>
  <header>
    <h1>タゴ'sクリエイト</h1>
    <nav>
      <p>Global-Navigation</p>
    </nav>
  </header>
  <main>
    <div class="scrollA scrollUp">
      <h2>Content</h2>
    </div>
    <div class="scrollA scrollUp">
      <h2>Content</h2>
    </div>
    <div class="scrollA scrollUp">
　　　　　　　　　　　　・
　　　　　　　　　　　　・
　　　　　　　　　　　　・
　　　　　　　　　　　　・
  </main>
  <script src="example.js"></script>
</body>
```

_JSコード_
```
window.addEventListener('load',fadeCheck);
window.addEventListener('scroll',fadeCheck,{passive:true});
function fadeCheck(){
  var cont=document.querySelectorAll('.scrollA');  //変更点１
  for(var i=0;i<cont.length;i++){ //変更点２
    if(window.innerHeight>cont[i].getBoundingClientRect().bottom){ //変更点３
      cont[i].classList.add('fadeJS'); //変更点４
    }
  }
}
```
CSSは先ほどまでのままで、JSを少し書き換え、HTMLのコンテンツ要素全てに同じクラスを付与しました。
またまたJSの上から変更や追加された記述を説明していきます。
変更点１、HTMLの対象要素が複数あるため、Allを使用しクラス名「.scrollA」のついている要素を全て取得、それを変数「cont」に代入します。
この「querySelectorAll」を使用し変数Xに代入すると、変数Xにインデックス番号が付与され、HTMLの上から１番目のクラスが「変数X[0]」となり、２番目が「変数X[1]」というふうになります。
変更点２、「.scrollA」クラスが付与されている要素の数だけ後の処理を繰り返すfor文を作成します。
変更点３、if文を作成し、「getBoundingClientRect」により複数の「cont」要素全てに対し、下辺を基準高さとし、「window.innerHeight（ブラウザの表示高さを数値化）」より小さい（画面下部よりさらに上に行き、ブラウザ上に見える状態）の場合という条件式を、インデックス番号0~6全てに適用します。
変更点４、複数「cont」要素全てに対し、条件が当てはまるごとに「fadeJS」というクラスを付与します。
![スクリーンショット 2022-04-06 22.28.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521240/026eb824-d112-12a0-fd5a-5e60866b0f4b.png)
画像じゃ分かりにくいですが、要素１つに対し適用していたフェードインアニメーションを、「content要素」の全てに適用することができました！