👋

Astro, GSAPでズームインアニメーションを実装する

2023/09/27に公開

はじめに

前回↓こちらの記事に書いたカウントアップアニメーションを実装しましたが、今回はその続きでズームインのアニメーションの実装を行いました。もしよろしければ下記添付の記事もご確認していただければと思います。
https://zenn.dev/shunf/articles/202308033-astro-gsap-countup
https://github.com/shun1121/astro-animation

主な使用技術

Reactをプロジェクトに入れていますが、今回の実装箇所では使用していません。

ディレクトリ構成

今回はsrc/comopnents/Zoomin/Zoomin.astroを新たに作成し、src/pages/index.astroにimportして使用しています。

  .vscode/
  node_modules
  public/
  src/
    ├─ components/
    │    ├─ Countup/
    │    │   ├─ Countup.astro
    │    ├─ Zoomin/
    │    │   ├─ Zoomin.astro   <----   *** New! ***
    ├─ layouts/
    │    ├─ Layout.astro
    ├─ pages/
    │    ├─ index.astro
    ├─ env.d.ts
  .gitignore
  astro.config.mjs
  package.json
  pnpm-lock.yaml
  README.md
  tailwind.config.cjs
  tsconfig.json

画像のズームイン実装

src/comopnents/Zoomin/Zoomin.astro

---
---

<div id="zoomin-trigger">
  <div class="relative h-screen w-full bg-black py-[60px] overflow-hidden">
    <img src="/autumn.jpg" id="zoomin-target" class="mx-auto object-fit" />
  </div>
</div>

<script>
  import { gsap } from "gsap";
  import { ScrollTrigger } from "gsap/ScrollTrigger";

  gsap.registerPlugin(ScrollTrigger);

  const ZoominTrigger = document.getElementById("zoomin-trigger");
  const ZoominTarget = document.getElementById("zoomin-target");
  gsap.set(ZoominTarget, {
    yPercent: -50,
    xPercent: -50,
    top: "50%",
    left: "50%",
    minWidth: "100%",
    position: "absolute",
  });

  const zoomInAnimation = gsap.fromTo(
    ZoominTarget,
    { scale: 1 },
    {
      scale: 6,
      duration: 5,
      ease: "expoScale(0.5, 2, power2.inOut)",
      repeat: 0,
    }
  );

  ScrollTrigger.create({
    trigger: ZoominTrigger,
    start: "46% center",
    end: "bottom center",
    animation: zoomInAnimation,
    markers: true,
  });
</script>

GSAPのインポート

以前のカウントアップアニメーションと同様に、ズームインアニメーションのトリガーにスクロールを当てているので、ScrollTriggerをインポートしてregisterPlugin()に登録します。

import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';

gsap.registerPlugin(ScrollTrigger);

画像の位置を設定

getElementByIdでアニメーションのトリガーになる要素とターゲット要素を取得します。次に.set()メソッドを使って第一引数にターゲットの要素を指定し、第二引数に初期値を設定していきます。

・xPercent、yPercent:

xPercentは水平方向への移動、yPercentは水鳥区方向への移動を設定できます。 今回はどちらも-50を指定して要素を真ん中に配置しています。

・top、left:

positionabsoluteをしており、topleft50%を指定して要素を真ん中に配置しています。

・minWidth:

要素の最小幅を100%に設定しており、親要素の幅に合わせて表示されます。

・position:

ZoominTargetであるimgタグの親要素にrelativeを使用しており、それに対してここではabsoluteを指定しています。

const ZoominTrigger = document.getElementById('zoomin-trigger')
const ZoominTarget = document.getElementById('zoomin-target')

gsap.set(ZoominTarget, {
  yPercent: -50,
  xPercent: -50,
  top: "50%",
  left: "50%",
  minWidth: "100%", 
  position: "absolute"
})

ズームインアニメーションを作成

fromTo()メソッドを使用して第一引数にターゲットの要素、第二引数にアニメーションの始まり、第三引数にアニメーションの終わりの処理を記述していきます。

・scale:

拡大率を設定できます。ここではアニメーションの開始時に1倍に設定し、終了時に6倍になるように指定しています。

・duration:

アニメーションの継続時間に関して今回は5秒に設定しています。

・ease:

主に、Tween(アニメーションの始まりから終わりの間を補完する機能)のタイミングを変更するために使用します。今回はexpoScale(0.5, 2, power2.inOut)を指定しており、第一、第二引数でアニメーションのスケールを記述し、第三引数でeasingの種類を設定しています。第三引数は任意で設定しなくても大丈夫です。
fromTo()メソッドで指定しているscaleの値は要素の拡大率についてであり、expoScale()で設定している数値とは関係ありません。

・repeat:

アニメーションの繰り返し実行に関する値で、今回は繰り返さずに1度きりで終了するようにを設定しています。

const zoomInAnimation = gsap.fromTo(
  ZoominTarget,
  { scale: 1 },
  {
    scale: 6,
    duration: 5,
    ease: "expoScale(0.5, 2, power2.inOut)",
    repeat: 0,
  }
);

スクロールトリガーの実装

スクロールに応じたトリガーやアニメーションを設定するためにScrollTrigger.createメソッドを使用します。メソッド内それぞれパラメータを指定していきます。

・trigger:

トリガーとなる要素を指定します。今回はZoominTriggerを当てています。

・start:

トリガーが開始される位置を指定します。現在は46% centerと記述しており、画面中央が要素ZooinTriggerの上から46%の位置を過ぎた時にアニメーションを開始します。

・animation:

トリガーがが発生した時に実行するアニメーションをここに指定します。今回はZoominAnimationを指定してズームインのアニメーションを当てています。

・marker:

トリガーの位置を確認するためのマーカーです。必要がなければfalseにしておきます。

ScrollTrigger.create({
  trigger: ZoominTrigger,
  start: "46% center",
  animation: zoomInAnimation,
  markers: true,
});

参考

https://greensock.com/docs/v3/Eases/ExpoScaleEase
https://ics.media/entry/220822/
https://codepen.io/fedechinaski/pen/KYVzNV

GitHubで編集を提案

Discussion