JavaScript

【GSAP】要素を遅らせてオープニングアニメーションを実装しよう

2023年10月15日

※ 当サイトではアフィリエイト広告を利用しています

要素を遅らせて実装するオープニングアニメーション

この記事では「GSAPで要素を遅らせてオープニングアニメーションを実装する方法」について解説します。

GSAPはWebサイトにアニメーションを実装することができるJavaScript系のライブラリです。GSAPでTimeLine、ScrollTriggerを組み合わせればおしゃれなオープニングアニメーションを実装することができます。

この記事を読むと...
  • GSAPでオープニングアニメーションを実装する方法が分かる
  • おしゃれなオープニングアニメーションが実装できる

なお、GSAPの導入方法や基本的な使い方については、以下の記事をご覧ください。

あわせて読む

また、ScrollTriggerの基本的な使い方に関しては、以下の記事をご覧ください。

あわせて読む

GSAPでオープニングアニメーションの実装

今回実装するオープニングアニメーションは以下のようになります。

See the Pen ScrollTriggerとパララックス by 山中滉大 (@tips-web) on CodePen.

<div class="l-container">
  <div class="p-opening">
      <span class="p-opening__mask"></span>
      <span class="p-opening__logo">Logo.inc</span>
  </div>
  <header class="l-header p-header">
    <div class="p-header__inner">
      <nav class="p-header__nav">
        <ul class="p-nav">
          <li class="p-nav__item"><a href="">メニュー1</a></li>
          <li class="p-nav__item"><a href="">メニュー2</a></li>
          <li class="p-nav__item"><a href="">メニュー3</a></li>
          <li class="p-nav__item"><a href="">メニュー4</a></li>
        </ul>
      </nav>
    </div>
  </header>
  <div class="p-fv">
    <div class="p-fv__inner">
      <div class="p-fv__textBox">
        <p class="p-fv__title">タイトルタイトル</p>
        <p class="p-fv__text">テキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト</p>
      </div>
        <div class="p-fv__img">
            <img src="https://drive.google.com/uc?export=view&id=1U2nyUpl2yUfoM7JwIGCEMmu0EPGnYxJU" alt="">
        </div>
    </div>
  </div>
</div>
.l-container{
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.p-opening{
  width: 100%;
  height: 100vh;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 99;
  display: flex;
  align-items: center;
  justify-content: center;
}

.p-opening__logo {
  color: #fff;
  font-size: 50px;
  display: block;
  z-index: 1;
  position: absolute;
  top: 50%;
}

.p-opening__mask{
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: top right;
  background-color: #010101;
  z-index: 1;
}

.l-header {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 80;
  width: 100%;
  height: 60px;
}

.p-header {
  background-color: #f7f7f7;
}

.p-header__inner {
  padding-right: 20px;
  padding-left: 20px;
  height: inherit;
  display: flex;
  align-items: center;
  justify-content: flex-end;
}

.p-nav {
  display: flex;
  align-items: center;
}

.p-nav__item a {
  width: 100%;
  display: block;
  font-size: 16px;
  color: #010101;
}

.p-nav__item {
  margin-right: 20px;
}

.p-nav__item:last-child {
  margin-right: 0;
}

.p-fv{
  width: 100%;
  height: 100vh;
  overflow: hidden;
  position: relative;
}

.p-fv__img {
  position: relative;
  width: 100%;
  height: inherit;
  clip-path: inset(0 100% 0 0);
  overflow: hidden;
  margin-right: calc(50% - 50vw);
}

.p-fv__img img{
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.p-fv__inner {
  display: flex;
  align-items: center;
  position: relative;
  justify-content: center;
  padding: 0 40px;
  height: inherit;
}

.p-fv__textBox {
  background-color: rgb(202, 235, 255);
  padding: 20px 30px;
  margin-right: -40px;
  position: relative;
  z-index: 5;
  clip-path: inset(0 100% 0 0);
  width: 100%;
  max-width: 500px;
}

.p-fv__title {
  font-size: 24px;
}

.p-fv__text {
  margin-top: 10px;
  font-size: 14px;
}
window.addEventListener('load', function () {
  const tl = gsap.timeline();
  tl
    .fromTo('.p-opening__logo', {
      autoAlpha: 0
    }, {
      autoAlpha: 1,
      delay: .5
    })
    .to('.p-opening__logo', {
      duration: .5,
      autoAlpha: 0,
      scale: 1.05,
    }, '+=1')
    .to('.p-opening__mask', {
      duration: 1.5,
      scaleX: 0,
      ease: 'power4.inOut'
    }, '-=.1')
    .to('.p-fv__img', {
      duration: 1.5,
      clipPath: 'inset(0 0% 0 0)',
      ease: 'power4.inOut',
      stagger: .1
    }, '-=.4')
    .to('.p-fv__textBox', {
      duration: 1.5,
      clipPath: 'inset(0 0% 0 0)',
      ease: 'power4.inOut',
      stagger: .1
    }, '-=.4')
    .from('.p-header', {
      duration: 1.5,
      y: -100,
      ease: 'power4.out',
    }, '-=1')
    .set('.p-opening', {
      autoAlpha: 0,
    })
})

画面を更新すると以下のような動きでオープニングアニメーションが流れます。

①背景が黒で画面中央にロゴの文字が出現

②ロゴがふわっと消えて、黒背景が左から右に向かって消える

③FVの画像が左から右に向かって表示

④FVのタイトルとテキストエリアが左から右に向かって表示

⑤最後にヘッダーが上から下に向かって下りてくる

オープニングアニメーションのイメージは以下のようになります。

オープニングアニメーションイメージ

アニメーション後の状態をつくる

まずは、オープニングアニメーション後のFVを作成します。ここでいったんGSAPのことを考えずにコーディングします。

なお、最初に表示される黒背景やロゴの部分は、以下のコードになります。

<div class="p-opening">
   <span class="p-opening__mask"></span>
   <span class="p-opening__logo">Logo.inc</span>
</div>
.p-opening{
  width: 100%;
  height: 100vh;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 99;
  display: flex;
  align-items: center;
  justify-content: center;
}

.p-opening__logo {
  color: #fff;
  font-size: 50px;
  display: block;
  z-index: 1;
  position: absolute;
  top: 50%;
}

.p-opening__mask{
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  background-color: #010101;
  z-index: 1;
}

ここから先で、GSAPでアニメーションを実装していきます。

ロゴと黒背景のアニメーション実装

まず、最初に表示される黒背景とロゴのアニメーションを実装します。

GSAPではTimeLineを使用します。

以下の部分で、loadイベントが発火したらGSAPの処理が動くようにイベント登録します。

window.addEventListener('load', function () {
 // ここにGSAPのコードを書く
})

GSAPのTimeLineを使用するので、gsap.timeline()を記述し、変数tl に格納します。

TimeLineの変数のあとに、fromTo()やto()など追記する形でアニメーションを設定していきます。なお、TimeLineは基本的に上からアニメーションが実行されていきます。

window.addEventListener('load', function () {
  const tl = gsap.timeline(); // GSAPのTimeLine使用
  tl
    //ここに個別のアニメーション設定を記述していく

})

以下の部分では、ロゴの透明度(autoalpha)を0から1にするアニメーションを設定しています。autoAlphaは0で非表示、1で表示なのでopacityプロパティと似たようなイメージで使用できます。

.fromTo('.p-opening__logo', {
    autoAlpha: 0
 }, {
    autoAlpha: 1,
    delay: .5
 })

次に、ロゴがscale:1.05;で1.05倍の大きさになりながらautoAplhaが0で非表示になります。

’+=1’というのは前のアニメーション(直前のfromToアニメーション)が完了する1秒後にロゴが1.05倍の大きさになりながら非表示になるアニメーションが実行される設定です。

.to('.p-opening__logo', {
      duration: .5,
      autoAlpha: 0,
      scale: 1.05,
}, '+=1') // 前のアニメーション完了する1秒後

+=1、-=0.2など細かいアニメーションの指定ができます。

例えば、-=0.2、のように記述すると、前のアニメーションが完了する0.2秒前に、アニメーションが発火する設定になります。

durationプロパティは、アニメーションの実行時間設定なので、上記の場合、0.5秒かけてアニメーションが実行されることを意味します。

次に以下の部分で黒背景をX軸方向に向かって非表示にします。

ease: ‘power4.inOut’は、イージングアニメーションの設定で、power4.in、power4.outなど細かいイージングを設定することできます。

.to('.p-opening__mask', {
    duration: 1.5,
    scaleX: 0,
    ease: 'power4.inOut'
}, '-=.1')

 現時点では、以下のように黒背景が左右から閉じるような動きでアニメーションします。

p-opening__mask要素にtransform-originプロパティを指定して、アニメーションの方向を適用させます。以下のようにtop rightと指定すると左から右に向かって黒背景が動くようになります。

.p-opening__mask{
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: top right; /* 追記 */
  background-color: #010101;
  z-index: 1;
}

次に、p-opening要素の透明度を0に設定します。これを設定しないと、黒背景が消えた後もp-opening要素は画面の最前面に表示されているため、ヘッダーなどのメニューをクリックできません。

該当コードは以下になります。

.set('.p-opening', {
    autoAlpha: 0,
})

 ここまでの処理をまとめると、以下のようになります。

window.addEventListener('load', function () {
  const tl = gsap.timeline();
  tl
    .fromTo('.p-opening__logo', {
      autoAlpha: 0
    }, {
      autoAlpha: 1,
      delay: .5
    })
    .to('.p-opening__logo', {
      duration: .5,
      autoAlpha: 0,
      scale: 1.05,
    }, '+=1')
    .to('.p-opening__mask', {
      duration: 1.5,
      scaleX: 0,
      ease: 'power4.inOut'
    }, '-=.1')

    .set('.p-opening', {
      autoAlpha: 0,
    })
})

FVの画像が左から右に向かって表示

黒背景とロゴが消えた後、FVの画像が左から右に表示されるアニメーションを実装します。

p-fv__img要素を、clipPathをアニメーションし、staggerで0.1秒の遅延を持たせています。

該当コードは以下になります。

.to('.p-fv__img', {
    duration: 1.5,
    clipPath: 'inset(0 0% 0 0)',
    ease: 'power4.inOut',
    stagger: .1
 }, '-=.4')

clipPathのinset(0 0% 0 0)はそれぞれ以下の意味をします。

  • 上辺からの距離0
  • 右辺からの距離0%
  • 下辺からの距離0
  • 左辺からの距離0

つまり、inset(0 0% 0 0)は上下左右4辺からクリップしない(切り取らない)ことを意味するので、アニメーション後は画像すべて表示を意味します。

CSSでは、以下のようにclip-pathプロパティでinset(0 100% 0 0)を指定します。これは、右辺から100%を切り取ることを意味しているので、画面では非表示になります。

.p-fv__img {
  position: relative;
  width: 100%;
  height: inherit;
  clip-path: inset(0 100% 0 0); /* 右辺から100%切り取り→非表示の意味 */
  overflow: hidden;
  margin-right: calc(50% - 50vw);
}

例えば、CSSでclip-path(0 50% 0 0);のように指定すると、左から50%部分までの画像が表示されることになります。

動きとしては、CSSで初期状態は画像を右辺100%切り取りで非表示にし、GSAPで右辺の切り取り0%にして表示される、という仕組みになります。

clip-pathの右辺が100%→0%へとアニメーションするので、画面上では、左から右に向かって画像が表示されるような動きになります。

clip-pathは以下のようなイメージです。

クリップパスイメージ

FVのタイトルとテキストエリアが左から右に向かって表示

画像左にある、タイトルとテキストエリア部分も画像と同様の処理をしています。

.p-fv__textBox {
  background-color: rgb(202, 235, 255);
  padding: 20px 30px;
  margin-right: -40px;
  position: relative;
  z-index: 5;
  clip-path: inset(0 100% 0 0); /* 右辺から100%切り取りで非表示 */
  width: 100%;
  max-width: 500px;
}
.to('.p-fv__textBox', {
    duration: 1.5,
    clipPath: 'inset(0 0% 0 0)', // 右辺0%で表示
    ease: 'power4.inOut',
    stagger: .1
}, '-=.4')

ここまでのGSAPのコードをまとめると以下のようになります。

window.addEventListener('load', function () {
  const tl = gsap.timeline();
  tl
    .fromTo('.p-opening__logo', {
      autoAlpha: 0
    }, {
      autoAlpha: 1,
      delay: .5
    })
    .to('.p-opening__logo', {
      duration: .5,
      autoAlpha: 0,
      scale: 1.05,
    }, '+=1')
    .to('.p-opening__mask', {
      duration: 1.5,
      scaleX: 0,
      ease: 'power4.inOut'
    }, '-=.1')
    .to('.p-fv__img', {
      duration: 1.5,
      clipPath: 'inset(0 0% 0 0)',
      ease: 'power4.inOut',
      stagger: .1
    }, '-=.4')
    .to('.p-fv__textBox', {
      duration: 1.5,
      clipPath: 'inset(0 0% 0 0)',
      ease: 'power4.inOut',
      stagger: .1
    }, '-=.4')
  .set('.p-opening', {
      autoAlpha: 0,
    })
})

ここまでの動きは以下のようになります。

最後にヘッダーが上から下に向かって下りてくる

最後に、ヘッダーが上から下に向かって下りてくるアニメーションを実装します。

y:-100でp-header要素を100px分y軸方向に移動しておき、アニメーション後では元の位置に戻ります。

該当コードは以下になります。

.from('.p-header', {
   duration: 1.5,
   y: -100,
   ease: 'power4.out',
}, '-=1')

これで、オープニングアニメーションが完成します。

まとめ

GSAPでオープニングアニメーションを実装する方法について解説しました。TimeLineを使うので、どのような順番でアニメーションしていくのか順番を考えながら実装していきましょう。

GSAPで本格的な学習をするためには10日間で学べるこちらの講座がおすすめです!

【たった"10日間"でWEBアニメーション実装スキル習得】GSAPマスター講座

今すぐ学習をはじめる>>

  • この記事を書いた人
アバター画像

こうだい

兼業でWeb制作事業|31歳|本業畑違いで知識0から学習開始→1年目で初案件獲得→2年で月の兼業受注金額70万円達成|4年目で100万円達成|兼業でも稼げることを確信|Web制作メンター|制作費無料のホームページ制作事業運営|コーディング・ホームページ制作についてお気軽にお問い合わせください

-JavaScript
-