🦸

GSAPの基本的な記述をまとめる

2023/06/22に公開

はじめに

JavaScriptのアニメーションライブラリ「GSAP」の基本的な記述や、よく使う機能をまとめたいと思います。
https://greensock.com/gsap/

GSAPはとても高機能で基本の部分となる記述を抑えるだけでも、工夫次第でいろんな表現ができます。当記事では触れませんがSVGやcanvasなどと組み合わせるとアニメーションの幅が一気に広がります。また、scrollTriggerMotionPathPluginなどプラグインもとても充実しています。

基本的な動きを組み合わせたイントロアニメーション

ループやリピート制御を組み合わせたエフェクト

連続的な処理

応用:canvasと組み合わせたイントロアニメーション

GSAPのインストール

npm install gsap
// for cdn
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.0/gsap.min.js"></script>
import {gsap} from "gsap";

基本のメソッド4つ

  • set – アニメーション対象要素の初期値を指定
  • to – アニメーション完了時の状態を指定
  • from – アニメーション開始時の状態を指定
  • fromTo – アニメーション開始時と終了時の状態を指定
基本的なメソッド
// set アニメーション対象要素の初期値を指定
const firstPosition = {
  x: 100, 
  y: 100, 
}
gsap.set('.box', {
  x: firstPosition.x, //x軸を100px移動
  y: firstPosition.y, //y軸を100px移動
})

// to アニメーション終了時の状態を指定
gsap.to('.box', 1, {
 // // x, y 100px移動した状態で終了
  x: 100, 
  y: 100, 
})

// from アニメーション開始時の状態を指定
gsap.from('.box', 1, {
  // x, y 100px移動した状態で開始
  x: 100,
  y: 100,
})

// fromTo アニメーション開始時と終了時の状態を指定
gsap.fromTo('.box', 1,
  // x, y -100px移動した状態で開始
  {
    x: -100,
    y: -100,
  },
  // x, y 100px移動した状態で終了
  {
    x: 100,
    y: 100,
  }
)

アニメーションでよく使うプロパティ

CSSアニメーションでもよく使うtransform類が指定できます。

  • 移動 – translate
  • 伸縮 – scale
  • 回転 – rotate
  • 歪み – skew
transform類
gsap.to('.box', 1,
  {
    // translate
    x: 100, // transform: translateX(100px)
    y: 100, // transform: translateY(10px)
    xPercent: -50, // transform: translateX(-50%)
    yPercent: -50,// transform: translateY(-50%)

    // scale 
    scale: 1.5, // transform: scale(1.5, 1.5)
    scaleX: 1.5, // transform: scaleX(1.5)
    scaleY: 1.5, // transform: scaleY(1.5)

    // rotate
    rotation: 180, // transform: rotate(180deg)
    rotationX: 180, // transform: rotateX(180deg)
    rotationY: 180, // transform: rotateY(180deg)

    // skew 
    skewX: 20, // transform: skew(20deg, 0)
    skewY: 20, // transform: skew(0, 20deg)
  }
)  

duration delay(時間制御)

  • duration – アニメーションの秒数を指定
  • delay – アニメーションの開始時間を指定
// duration 
// 第二引数に指定
gsap.to('.box', 1, { // 1秒かけてアニメーション
  x: '100px',
})
//or
// オブジェクトのキーに指定
gsap.to('.box', {
  x: '100px',
  duration: 1, // 1秒かけてアニメーション
})

// delay 
gsap.to('.box', {
  x: '100px',
  delay: 1, // 1秒後にアニメーション
})

opacity autoAlpha(透過制御)

フェードエフェクトなどでopacityで透過処理をする際、同時にvisibility: hidden;をつけたい場合に、autoAlphaを使用することで、opacityとvisibilityを指定することができます。

gsap.fromTo('.box',
  {
    autoAlpha: 0, // opacity: 0;とvisibility: hidden;を指定
  },
  {
    autoAlpha: 1, // opacity: 1;とvisibility:visible;を指定
  }
);

また、display: none;を指定したい場合は、onCompleteの関数内で直接指定する必要があります。

const box = document.querySelector('.box')
gsap.fromTo(box ,
  {
    opacity: 0,
    onComplete: () => {
      box.style.display = 'none' 
    }
  },
  {
    opacity: 1,
    onComplete: () => {
      box.style.display = 'block' 
    }
  }
);

アニメーションの繰り返し

  • repeat – 繰り返しの回数
  • repeatDelay – 繰り返しするまでの遅延
  • yoyo – 繰り返し時に反転する
  • yoyoEase – 反転の際のイージング
gsap.to('.box', 1, {
  repeat: -1, // -1で無限に繰り返す
  repeatDelay: .5, // 0.5秒後に繰り返す
  yoyo: true, // 繰り返し時に反転する
  yoyoEase: 'power1.out', // 反転の際のイージング
})

複数要素をずらしてアニメーション


stragger – 複数要素を遅延させる際に使用

  • each – 遅延させる時間
  • from – 開始位置の指定
  • start – 始めの要素から
  • end – 最後の要素から
  • center – 真ん中の要素から
  • edges – 始めと終わりの要素から同時に
  • ramdom – ランダムに
gsap.set('.list__item', {
  y: 30,
  opacity: 0
})

gsap.to('.list__item', 1, {
  y: 0,
  opacity: 1,
  ease: 'expo.out',
  stagger: {
    each: .1, // 遅延させる時間
    from: 'start' // 開始位置の指定 start, end, center, edges, random
  }
})

straggerのデモ

キーフレーム(Keyframes)

CSSアニメーションでよく使うkeyframesもgsapで記述できます。
二次元配列や、css同様でパーセントの指定ができます。

// keyframes
// 書き方1
gsap.to('.box', 4, {
  keyframes: {
    x: [0, 100, 100, 0, 0],
    y: [0, 0, 100, 100, 0],
    ease: 'power4.out',// 全体のイージング
    easeEach: 'power4.out'// 個々のイージング
  }
})

// 書き方2
gsap.to('.box', 3, {
  keyframes: [
    {
      x: 100,
      y: 100,
    },
    {
      x: 0,
      y: 0
    },
    {
      rotation: 180
    }
  ],
  ease: 'expo.out',// 全体のイージング
  easeEach: 'power4.out'// 個々のイージング
})

// 書き方3
gsap.to('.box', 3, {
  keyframes: {
    '0%': {
      x: 100,
    },
    '50%': {
      y: 100,
    },
    '100%': {
      x: 0,
      y: 0
    }
  },
  ease: 'expo.out',// 全体のイージング
  easeEach: 'power4.out'// 個々のイージング
})

制御用のメソッド

  • play() – アニメーションの開始
  • pause() – 一時停止
  • resume() – 一時停止から再開
  • restart() – リスタート
  • reverse() – 逆再生
  • seek(num) – 引数の値の秒数地点での表示を確認できる(デバッグ時に有効)
  • timeScale(num) – 引数の値の倍速で再生(速度調整)
  • duration(num) – 引数の値のdurationを設定
// 制御用メソッド
const animation = gsap.to('.box', 3, {
  x: 200,
  paused: true, // 停止状態に
})

// クリックイベントの指定
function clickFunction(id, method) {
  document.getElementById(id).addEventListener('click', () => {
    method()
  })
}

// アニメーション制御時によく使うメソッド
clickFunction('play', () => animation.play()) // アニメーションの開始
clickFunction('pause', () => animation.pause()) // 一時停止
clickFunction('resume', () => animation.resume()) // 一時停止から再開
clickFunction('restart', () => animation.restart()) // リスタート
clickFunction('reverse', () => animation.reverse()) // 逆再生

// デバッグ時によく使うメソッド
clickFunction('seek', () => animation.seek(2))// 引数に入れられた数値の秒数地点での表示を確認できる(デバッグ時に有効)
clickFunction('timeScale', () => animation.timeScale(1))// 引数の値の倍速で再生(速度調整)
clickFunction('duration', () => animation.duration(1))// 引数の値のdurationを設定

タイムライン(timeline)

初期化した後にメソッドチェーンでつなげることで、連続的な処理を行うことができます。

// 要素を指定してメソッドチェーンで記述
const tl = gsap.timeline()
tl.to('.box', 1, {
  x: 200
})
.to('.box', 1, {
  y: 200,
  rotation: 90
})
.to('.box', 1, {
  x: 0,
  rotation: 360
})
.to('.box', 1, {
  y: 0,
  rotation: 0
})

timelineでのアニメーションの開始時間の制御

アニメーションの開始時間などを、to()などのメソッドの第3または第4引数に指定することができます。

  • 数値 – 指定時間後にアニメーションを開始、※timelineではtimeline全体の時間を基準に考える
  • +=1 – そのアニメーション自身を基準に1秒後に発火、delay: 1と同じ
  • -=2 – そのアニメーション自身を基準に2秒前に発火、delay: -2と同じ
  • < – 直前のアニメーションの開始時に発火
  • >3 – 直前のアニメーションが終わってから、3秒後に発火
  • <4 – 直前のアニメーションが始まってから、3秒後に発火
const tl = gsap.timeline()
tl.to('.box', 1, {
  x: 100,
  backgroundColor: 'red'
})
  .to('.box', 1, {
    y: 100,
    backgroundColor: 'blue'
  })
  .to('.box', 1, {
    x: 0,
    backgroundColor: 'orange'
  }, '<') // < 直前のアニメーション開始時に発火
  .to('.box', 1, {
    y: 0,
    backgroundColor: 'green'
  })

timelineの連結、ネスト

timelineの連結

タイムライン1の後にタイムライン2を発火させたいといった場合には.add()を使用することで2つのタイムラインを連結させることができます。

const tl = gsap.timeline()
tl
.to('.box1', 1, {
  y: 30,
})
.to('.box1', 1, {
  opacity: 0
})

const tl2 = gsap.timeline()
tl2
.to('.box2', 1, {
  y: 30,
})
.to('.box2', 1, {
  opacity: 0
})

tl.add(tl2)// timeline連結(tl終了後にtl2が発火)

timelineのネスト

timelineを返した関数をgsap.timeline.add()にコールバックとして渡すことで連結することができます。

// scene1を作成
function scene1(target) {
  const tl = gsap.timeline()
  tl
  .to(target, 1, { y: 100 })
  .to(target, 1, { x: 100 })
  return tl // タイムラインを返す
}

// scene2を作成
function scene2(target) {
  const tl2 = gsap.timeline()
  tl2
  .to(target, 1, { y: 0, })
  .to(target, 1, { x: 0 })
  return tl2 // タイムラインを返す
}

// scene3を作成
function scene3(target) {
  const tl3 = gsap.timeline()
  tl3
  .to(target, 1, { y: -100 })
  .to(target, 1, { x: -100 })
  return tl3 // タイムラインを返す
}

// 親のタイムラインを作成
// scene1の後にscene2とscene3が同時に発火
const master = gsap.timeline()
  .add(scene1('.box1'))
  .add(scene2('.box2'))
  .add(scene3('.box3'), '<') //scene2開始時に発火

コールバック

  • onStart – アニメーション開始時の処理
  • onComplete – アニメーション終了時の処理
  • onUpdate – アニメーション開始から終了までの間、処理され続ける
  • onRepeat – リピートされたアニメーションの開始時の処理
  • onReverseComplete – リバースされたアニメーションの終了時の処理
const tween = gsap.to('.box', 3, {
  x: 300,
  delay: 1,

  onStart: () => {
    // アニメーション開始時の処理
  },
  onComplete: () => {
    // アニメーション終了時の処理
  },
  onUpdate: () => {
    // アニメーション開始から終了までの間、処理され続ける
    
    // progress()を使用してアニメーションの進捗状況を取得できる
    // 進捗バーやローディングなどで使える
    const progress = Math.floor(tween.progress() * 100)
    document.getElementById('progress').textContent = `${progress}%`
  },
  onRepeat: () => {
    // リピートされたアニメーションの開始時の処理
  },
  onReverseComplete: () => {
    // リバースされたアニメーションの終了時の処理
  }
})

Effects(アニメーションの登録)

よく使うアニメーションを登録して、呼び出すことができます。

gsap.registerEffect({
  // 名前
  name: 'fadeOut',

  // デフォルト値
  defaults: {
    duration: 1,
    delay: 1,
    position: 30
  },

  // アニメーションの内容
  effect: (targets, config) => {
    return gsap.to(targets, {
      opacity: 0,
      ease: 'power2.out',

      // デフォルトのオプションを使いつつ、変更可能のオプションを指定
      y: config.position,
      duration: config.duration,
      delay: config.delay,
    })
  },

  // timeline内で使う場合は以下を指定
  extendTimeline: true
})

// エフェクトを呼び出す(timelineなし)
gsap.effects.fadeOut('.box')

// エフェクトを呼び出す(timelineあり)
const tl = gsap.timeline() 
tl.to('.box', 1, {
  y: -30
})
.fadeOut('.box', {
  delay: 0
})

参考

https://greensock.com/scrolltrigger/
https://greensock.com/docs/v3/Plugins/MotionPathPlugin

frontend flat

Discussion