[jQuery]スクロールしたらふわっと表示するよくあるアレの実装方法


#demo
###パターン1（シンプルに対象が画面に入ったら表示）
<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="js,result" data-user="Ficus-tsuji" data-slug-hash="poNoxOp" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Scroll表示1">
  <span>See the Pen <a href="https://codepen.io/Ficus-tsuji/pen/poNoxOp">
  Scroll表示1</a> by Takuya Tsuji (<a href="https://codepen.io/Ficus-tsuji">@Ficus-tsuji</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
###パターン2（トリガー対象が画面に入ったら子要素が順番に表示）
<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="js,result" data-user="Ficus-tsuji" data-slug-hash="YzpzRPw" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Scroll表示2">
  <span>See the Pen <a href="https://codepen.io/Ficus-tsuji/pen/YzpzRPw">
  Scroll表示2</a> by Takuya Tsuji (<a href="https://codepen.io/Ficus-tsuji">@Ficus-tsuji</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


#使い方
1. トリガーとなる対象要素に予め`class="offs"`をつけておきます。
2. 画面に入ったら`offs`が`ons`に変わるので、あとはCSSでよしなに`transition`を使ってアニメーションを設定します。
3. 順番に遅延して表示させる場合は`data-delay`属性にトリガーしてから遅延する秒数を設定しておくと、`transition-delay`が付くのでちょっと便利です。


###特徴
・jsでやっているのは、ほぼクラスをoffsからonsに付け替えることだけ。
・アニメーションはcssを使用するので動きが軽いです。
・一度onsにクラスが変わってから、上にスクロールして画面下に対象コンテンツが見えなくなると、またクラスがoffsに戻ります。


#コード
###HTML
```index.html
<!-- パターン1
（シンプルに対象が画面に入ったら表示） -->
<div class="fadeIn_item offs">画面に入ったら表示！</div>

<!-- パターン2
（トリガー対象が画面に入ったら子要素が順番に表示） -->
<ul class="offs">
  <li class="fadeIn_item">画面に入ったら順番に表示！</li>
  <li class="fadeIn_item" data-delay="0.2">画面に入ったら順番に表示！</li>
  <li class="fadeIn_item" data-delay="0.4">画面に入ったら順番に表示！</li>
</ul>
```


###SCSS(下からふわっとする場合はこんな感じ)
```animation.scss
.fadeIn_item{
  &.offs,
  .offs &{
    opacity: 0;
    transform: translateY(50px);
  }

  &.ons,
  .ons &{
    transition: all 1s cubic-bezier(0, 0, 0.13, 0.79);
    opacity: 1;
    transform: translateY(0);
  }
}
```
CSSの場合はこちら↓

```animation.css
.fadeIn_item.offs,
.offs .fadeIn_item{
  opacity: 0;
  transform: translateY(50px);
}
.fadeIn_item.ons,
.ons .fadeIn_item{
  transition: all 1s cubic-bezier(0, 0, 0.13, 0.79);
  opacity: 1;
  transform: translateY(0);
}
```

###jQuery

```scroll.js
/*
スクロール出現
*/
// スクロール出現用関数（.offs ⇄ .ons）
function scr_ani(scr,offs_max){
  var
  window_h = $(window).height(),
  offs_length = $('.offs').filter(':visible').length,
  ons_length = $('.ons').filter(':visible').length,
  wh_pos = 20;// 対象コンテンツの上端が画面下からどれくらい入ったら反応するか。画面高さに対する割合（%）
  if(offs_length){
    var first_item = offs_max - offs_length;
    for (var i=0; i<offs_length; i++) {
      var data_scr = first_item + i;
      var offs = $('.offs[data-scr="' + data_scr + '"]');
      var target = offs.offset().top;
      var trigger = target - (window_h + scr - window_h * wh_pos / 100);
      if(trigger < 0){
        offs.removeClass('offs').addClass('ons');
      }else{
        break;
      }
    }
  }
  if(ons_length){
    var last_item = ons_length - 1;
    for (var i=0; i<ons_length; i++) {
      var data_scr = last_item - i;
      var ons = $('.ons[data-scr="' + data_scr + '"]');
    	var target = ons.offset().top;
      var trigger = target - (window_h + scr);
      if(trigger > 0){
        ons.removeClass('ons').addClass('offs');
      }else{
        break;
      }
    }
  }
};

$(function(){

  // スクロール出現アイテムにナンバリング（hide要素には適用されません）
  var cnt = 0;
  for (var i=0; i<$('.offs').length; i++) {
    if($('.offs').eq(i).is(':visible')){
      $('.offs').eq(i).attr('data-scr',cnt);
      cnt++;
    }
  }
  // 対象要素の個数
  var offs_max = $('.offs').filter(':visible').length;

  // （リロード時など）ロード時にすでにスクロールされている場合に対応
  var scr = $(window).scrollTop();
  scr_ani(scr,offs_max);


  /************
  スクロール時
  ************/
  $(window).on('scroll', function(){
    var scr = $(window).scrollTop();
    scr_ani(scr,offs_max);
  });// end scroll

});
```