GSAPでスクロールしていくと窓枠が拡大していく実装をやってみた(備忘録)

今回は、透明な窓枠がスクロールすると拡大しながら後ろ側の背景が現れていくといった実装をしてみました。窓枠に限らずいろんな形で対応できるようになっています。

なお、スクロール位置を固定して拡大するようにやってみたかったのですが、なかなかうまくいかなかったため、今回はスクロールもしながら拡大していく実装になっています。スクロール固定については見通しが立てば別記事で書きたいと思っています。

今回用意したsvg画像について

Figmaで下記の手順で作成しています。

丸と正方形を作成します。

丸と正方形を選択して、選択範囲の結合をクリックします。

フレームと同じ大きさの長方形について、結合した下のレイヤーに用意し、フレームを選択した状態で、「選択範囲の型抜き」をクリックします。

下記のように窓枠がくり抜かれた図形が完成しますので、svgで書き出します。

これで準備が整いました。窓枠に限らずいろんな図形で試すことができますので、是非やってみてください。

HTMLの記述について

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>GSAPでスクロールしていくと窓枠が拡大していく</title>
  <link rel="stylesheet" href="../reset.css">
  <link rel="stylesheet" href="./style.css">
</head>

<body>
  <main>
    <div class="door-mask">
      <img src="./images/door-mask.svg" alt="">
    </div>
    <div class="content">
      <img src="./images/img_01.webp" alt="Image 1">
      <img src="./images/img_02.webp" alt="Image 2">
      <img src="./images/img_01.webp" alt="Image 3">
      <img src="./images/img_02.webp" alt="Image 4">
      <img src="./images/img_01.webp" alt="Image 5">
      <img src="./images/img_02.webp" alt="Image 6">
    </div>
  </main>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollTrigger.min.js"></script>
  <script src="./style.js"></script>
</body>

</html>

door-maskで囲われている部分が今回の窓枠の画像になります。contentで囲われている箇所は、窓枠が拡大されたときに表示される中身になっています。

下記はGSAPで使うのに必要な記述です。CDNを使っています。

公式の詳細はこちら

<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollTrigger.min.js"></script>

CSSの記述について

@charset "utf-8";

/* ==========================
  初期設定
========================== */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  position: relative;
  word-wrap: break-word;
}

img {
  width: 100%;
  vertical-align: bottom;
}

/* レイアウト設定 */
.door-mask {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 10;
  overflow: hidden;
}

.door-mask img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.content {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
}

door-mask部分は、positionをfixedにして固定しています。content部分はページ上部に合わせたいので、positionをabsoluteにして調整しています。

JavaScriptの記述について

"use strict";

// GSAPライブラリからScrollTriggerプラグインを登録
gsap.registerPlugin(ScrollTrigger);

// .door-maskクラスを持つ要素を選択
const doorMask = document.querySelector(".door-mask");

// .door-mask内のimg要素を選択
const doorMaskImg = document.querySelector(".door-mask img");

// GSAPタイムラインを作成。スクロールトリガー設定を含む
const tl = gsap.timeline({
  scrollTrigger: {
    trigger: ".door-mask", // トリガーとなる要素
    start: "top top", // トリガー開始位置:ビューポートの上部で開始
    end: "bottom top", // トリガー終了位置:ビューポートの下部で終了
    scrub: true, // アニメーションの進行状況を ScrollTrigger の進行状況に直接リンク
  },
});

// doorMaskImgのスケールを変更するアニメーション
tl.to(doorMaskImg, {
  scale: 6, // 最終的なスケール値
  ease: "none", // アニメーションのイージング設定:なし
});

コメントアウトにやっている詳細はコメントしています。

timelineを作成してscrolltriggerを設定しています。

door-maskをトリガーとして、開始位置と終了位置を設定し、door-mask imgの大きさがscale6に変化するようアニメーションを設定しています。

コード量は少ないですが、これでやりたい動きは完成しました。

あとは固定するパターンが作れればいいなと思っていますが、時間が溶けそうなため、できることからコツコツやっていこうと思います。