「IntersectionObserver」でスクロールでフワッとコンテンツ表示を実装してみよう

# IntersectionObserverとは？
MDNによると

「交差オブザーバー API (Intersection Observer API) は、ターゲットとなる要素が、祖先要素または文書の最上位のビューポートと交差する変化を非同期的に監視する方法を提供」
とあります。

今回は
これを使って「viewportと画像要素が重なった時に画像をフワッと表示させる方法」を開設していきます

こんな感じのやつです。スクロールするとフワッとでてくるやつ。（伝われ）
![Animation_3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332464/d8dd69a0-d597-9661-680a-176b67b95c82.gif)

参考文献:
[MDN 交差オブザーバー API](https://developer.mozilla.org/ja/docs/Web/API/Intersection_Observer_API)
[MDN IntersectionObserver()](https://developer.mozilla.org/ja/docs/Web/API/IntersectionObserver/IntersectionObserver)
# 使い方

1. テスト用のhtmlを用意してください。その中にimg要素を置いてください。
この時にとにかく長いテキストだったり要素を置いてimgが画面スクロールしないと見えないように配置してください。(cssとscriptを設定するのを忘れずに）

今回はこのhtmlをベースにやっていきます。
~~こんにちはが多すぎて狂気とか考えてはいけない。~~

これを使う場合、画像は適宜皆さんで差し替えてくださいね。

この後の作業はJavaScriptのファイルで行っていきます。JavaScriptファイルを作成し、
先頭に `'use strict';`と記述しておいてください。
```html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="style.css">
  <title>My Site</title>
</head>
<body>
  <h1>靴紹介</h1>
  <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
  <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
  <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
  <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
  <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
  <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
  <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>

  <img src="img/feature1.jpg" width="300", height="200">

  <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
  <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
  <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
  <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>

  <img src="img/feature2.jpg" width="300", height="200">
  
  <script src="main.js"></script>
</body>
</html>
```
2 . observerは要素の変化を監視してくれるものです。監視対象を用意します。img要素を取得していきましょう
```js
  const targets = document.querySelectorAll("img");
```

3 . 次に、`IntersectionObserver()` コンストラクターを使って IntersectionObserver オブジェクトを作っていきます。

```js
  const observer = new IntersectionObserver();
```

4 . IntersectionObserver関数は引数に関数オブジェクトを必要とします。これはMDNの
[IntersectionObserver()](https://developer.mozilla.org/ja/docs/Web/API/IntersectionObserver/IntersectionObserver)で見ることができます。
それでは次のステップで関数を定義していきます。
```js
// MDNから参照
new IntersectionObserver(callback)
new IntersectionObserver(callback, options)
```

5 . 今回はこんな感じの関数を定義します
```js
  function callBack(){
    console.log("交差したよ！");
  }
```
6 . IntersectionObserver()の引数の中に関数を入れていきましょう

```js
  const observer = new IntersectionObserver(callBack);
```

7 . 監視対象を監視します。監視するにはこのような記述をします
```js
  //.observeメソッドでターゲットを監視する
  observer.observe(/*ここに監視対象を記述*/);
``` 

8 . 今回は`querySelectorAll`で監視対象を配列として複数取得してきたためforeachで配列の要素全てに監視を付けましょう。
```js
  targets.forEach(element =>{
    observer.observe(element);
  });
```

9 . いよいよ実行です。作成したhtmlのパスをurlにコピペして実行します。
(chromeブラウザで実行します)

ページが開いたら
右クリック→検証→コンソールを開いてください
(交差したよ！が出れば成功です)
![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332464/3a7b0664-28e5-a6b1-ccb2-ce93a61a613d.gif)

10 . 画面をスクロールします。コンソールの数値が増え、複数回関数が呼び出されていることが分かります。

![Animation_2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332464/149d770b-1e52-f6b5-7ea7-3c00d6a6fe77.gif)

observerが関数を返すときは大きく分けて3つあります。
・「画面が表示されたとき(監視を開始するとき)」
・「対象とviewportが0％重なった時」
(これはviewportに対象が入る時(in)と対象が画面外から出る時(out)の2回呼び出されます)

11 . このようなcssを用意しておきます
```css
img{
  opacity: 0;
  transition: opacity 2.0s;
}

img.appear{
  opacity: 1;
}
```

12 . 監視対象と重なり交差したときだけ処理を行うようにcallback関数を書き換えましょう。重なった対象のクラスにappearを設定するように変更を加えます。

```js
  function callBack(entrys, obs){
    entrys.forEach(entry =>{
      //isIntersectingは交差地点にいるとtrue交差地点外にいるとfakseを返す
      if(!entry.isIntersecting){
        return;
      }
      console.log("交差したよ！");
      entry.target.classList.add("appear");
    });
  }
```
この新しく生えてきた「entrys」と「obs」は何ぞや？って話なんですが
これはIntersectionObserverの仕様で関数オブジェクトに2つの値を渡すのが関係しています。
この二つのことに関して書くと長くなりすぎるので

`entriesには交差した監視要素の配列が入っていて`
`obsには監視しているobserverそのものが入っている`
そう考えてもらえばOKです。
entrysのisIntersectingプロパティには
交差してるのかしてないのかがtrueかfalseで入っています。
これを使って
「ページ表示時にメソッドの処理が勝手に動いてしまう」事故を未然に防いでいます。

12. さて、説明も終わったところで実行してみてください。もし分からないことがあればMDNなどで自分で調べながらやってみましょう。
![Animation_3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332464/d8dd69a0-d597-9661-680a-176b67b95c82.gif)