TweenMaxとScrollMagicを使ってスクロールアニメーションを行う #1

## はじめに
今の勤務先で少し前から主にフロントエンドを担当することとなり、最近はVue.jsでSPAを構築したりしているのですが、直近でパララックスを用いたWebサイト制作の案件があり、そこでもフロントエンド側を担当することとなりました。
以前パララックスを用いたサイトを構築したことはあり、元々ごりごりコードを書くことが好きなので、その時はJavaScriptから何から自前で構築していったのですが、このライブラリ戦国時代（？）ならライブラリの使い方も知っておく必要があるなという考えから、今回は「TweenMax」と「ScrollMagic」を使用することにしました。

### TweenMaxについて
高機能なHTML5アニメーションライブラリです。
今回の案件では必要ありませんが、使いこなせばかなり複雑なアニメーションの構築も可能なようです。
有料サイトや有料アプリではライセンスの購入が必要になるので注意。

### ScrollMagicについて
スクロールイベントのトリガーを管理するライブラリです。
ごちゃごちゃしがちなトリガーを、一貫性を持って簡潔に記述することが可能です。
TweenMaxをプラグインとして読み込んで連動させることができるので相性抜群です。

今回は2回に分けて、以下のような記事を書きたいと思います。
1. アニメーションはTweenMaxを使用し、スクロールイベントのトリガーは自作
2. 1のトリガーをScrollMagicに置き換え

## 今回の記事のサンプル
まずはサンプルから。
`div#row-a`では背景色の変化、`div#row-b`では白いボックスが順に表示されるアニメーションを行っています。

<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="js,result" data-user="soraxism" data-slug-hash="pozEqrM" 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="TweenMax Sample">
  <span>See the Pen <a href="https://codepen.io/soraxism/pen/pozEqrM/">
  TweenMax Sample</a> by Soraxism (<a href="https://codepen.io/soraxism">@soraxism</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

## TweenMaxの読み込み
TweenMaxの外部JavaScriptファイルを読み込むには以下の方法用意されています。
1. [公式サイト](https://greensock.com/)からダウンロード
2. CDNからの読み込み
3. npmを使用してのインストール

今回は簡潔にするために2の方法を取ります。
またjQueryでの記述を併用するため、jQueryの外部JavaScriptファイルも併せてCDNから読み込んでいます。

```HTML:HTML
<!-- jQuery本体 -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- TweenMax本体 -->
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenMax.min.js"></script>
```

## HTMLとCSSについて
HTMLとCSSについては特に変わったことは行っていません。
強いて言えば`.item`を透明状態から出現されるために、あらかじめ`opacity: 0`を指定しているくらいです。

```HTML:HTML
<!-- 背景色が変化 -->
  <div id="row-a" class="row"></div>
  <!-- itemを順に表示 -->
  <div id="row-b" class="row">
    <ul class="items items--vertical">
      <li class="item"></li>
      <li class="item"></li>
      <li class="item"></li>
    </ul>
  </div>
```

```CSS:CSS
/* reset.cssは別途読み込み */

ul {
  list-style: none;
}

.row {
  width: 100%;
  height: 100vh;
  position: relative;
}

#row-a {
  background: #f44336;
}
#row-b {
  background: #03a9f4;
}

.items {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.item {
  width: 100px;
  height: 100px;
  background: #fff;
  opacity: 0;
}

.items--vertical .item {
  transform: translateX(20px);
}
.items--vertical .item + .item {
  margin-top: 10px;
}
```

## TweenMaxの基本的な使い方
TweenMaxの基本的な使い方は以下のような記述になります。

```JavaScript:JavaScript
TweenMax.要素の操作方法("要素の指定", アニメーションスピード, CSSプロパティオブジェクト)
```

### 要素の操作方法
主に以下のものがあります。
1. set：アニメーションは行わず、CSSのみを設定する
2. to：CSS初期値から、指定したCSSプロパティへアニメーションを行う
3. from：指定したCSSプロパティから、CSS初期値へアニメーションを行う
4. fromTo：上記2と3を同時に指定できる
5. staggerTo：指定の要素に対して、指定した秒間で順にアニメーションを行う

### 要素の指定方法
`div`や`.item`のように、CSSのセレクタ形式で記述します。

### アニメーションスピード
アニメーションの開始から終了までの時間を指定。単位は秒です。

### CSSプロパティオブジェクト
オブジェクト形式でCSSのプロパティと値を設定します。
`transform: traslateX(10px)`を`x: 10px`と書けるなど、簡潔な記述方法も用意されています。

## JavaScriptについて
詳細はコメントに記載していますが、ざっくりとは`.row`のオフセットトップの値を取得して、スクロールトップがその値を超えた場合にTweenMaxでアニメーションを指定しています。（今回はtoとstaggerToを使用）

```JavaScript:JavaScript
$(function() {
  // 各rowのオフセットトップを取得
  let a_top = $('#row-a').offset().top
  let b_top = $('#row-b').offset().top
  // スクロールトップが各rowのオフセットトップの-50の位置でアニメーション開始
  const negative = 50
  // アニメーションスピードの指定
  const speed = 1
  
  $(window).scroll(function() {
    // スクロールトップの取得
    let scroll_top = $(this).scrollTop()
    
    // #row-aのアニメーショントリガー
    if (scroll_top >= a_top) {
      TweenMax.to(
        '#row-a', // 要素の指定
        speed, // アニメーションスピード
        {
          // 背景色を変化させる
          backgroundColor: '#4caf50'
        }
      )
    }

    // #row-bのアニメーショントリガー
    if (scroll_top >= b_top - negative) {
      TweenMax.staggerTo(
        '#row-b .item', // 要素の指定
        speed, // アニメーションスピード
        {
          x: '-20px', // x方向へ-20px
          opacity: 1  // 透明度を1へ
        },
        0.2 // 0.2秒置きに順に実行
      )
    }
  })
})
```

## まとめ
この程度のアニメーションであればjQueryの`animate`を使用して記述してもさほど変わりはありませんが、次回ご紹介するScrollMagicとの連携や、もっと複雑なアニメーションを実装する場合に威力を発揮します。
日本では普及率がイマイチ？のようですが、海外ではよく使われているライブラリのようなので、覚えておいて損はないと思います。

[次回](https://qiita.com/soraxism/items/f2d885e1bf95e3803fc6)はJavaScriptのスクロールによるトリガー部分をScrollMagicに置き換えたものをご紹介します。