【javascript・gsap】3枚の画像を切り替える方法(3本ライン)

私がWebサイト制作でハマった事や良かった方法などを備忘録としてまとめています。

HTML

          <!-- top-kv Start -->
      <div class="top-kv js-flip">
        <div class="js-flip-kv js-flip--kv1">
          <!-- 上 -->
          <img
            src="/img/bg-top-kv1.png"
            width="1366"
            height="685"
            alt="top-kv"
            decoding="async"
            class="js-flip-part--top"
          />

          <!-- 中 -->
          <img
            src="/img/bg-top-kv1.png"
            width="1366"
            height="685"
            alt=""
            decoding="async"
            class="js-flip-part--middle"
          />

          <!-- 下 -->
          <img
            src="/img/bg-top-kv1.png"
            width="1366"
            height="685"
            alt=""
            decoding="async"
            class="js-flip-part--bottom"
          />
        </div>

        <div class="js-flip-kv js-flip--kv2">
          <!-- 上 -->
          <img
            src="/img/bg-top-kv2.png"
            width="1366"
            height="685"
            alt="top-kv"
            decoding="async"
            class="js-flip-part--top"
          />

          <!-- 中 -->
          <img
            src="/img/bg-top-kv2.png"
            width="1366"
            height="685"
            alt=""
            decoding="async"
            class="js-flip-part--middle"
          />

          <!-- 下 -->
          <img
            src="/img/bg-top-kv2.png"
            width="1366"
            height="685"
            alt=""
            decoding="async"
            class="js-flip-part--bottom"
          />
        </div>

        <div class="js-flip-kv js-flip--kv3">
          <!-- 上 -->
          <img
            src="/img/bg-top-kv3.png"
            width="1366"
            height="685"
            alt="top-kv"
            decoding="async"
            class="js-flip-part--top"
          />

          <!-- 中 -->
          <img
            src="/img/bg-top-kv3.png"
            width="1366"
            height="685"
            alt=""
            decoding="async"
            class="js-flip-part--middle"
          />

          <!-- 下 -->
          <img
            src="/img/bg-top-kv3.png"
            width="1366"
            height="685"
            alt=""
            decoding="async"
            class="js-flip-part--bottom"
          />
        </div>
      </div>

SCSS

.js-flip {
  overflow: hidden;
  position: relative;

  .js-flip-kv {
    position: absolute;
    inset: 0;

    &.js-flip--kv1 {
      z-index: 4;
    }
    &.js-flip--kv2 {
      z-index: 3;
    }
    &.js-flip--kv3 {
      z-index: 2;
    }

    img {
      position: absolute;
      width: 100%;
      height: 100%;
      object-fit: cover;

      &.js-flip-part--top {
        clip-path: polygon(
          0% 0%,
          100% 0%,
          100% calc(33.33% + 1px),
          0% calc(33.33% + 1px)
        );
      }

      &.js-flip-part--middle {
        clip-path: polygon(
          0% calc(33.33% - 1px),
          100% calc(33.33% - 1px),
          100% calc(66.66% + 1px),
          0% calc(66.66% + 1px)
        );
      }

      &.js-flip-part--bottom {
        clip-path: polygon(
          0% calc(66.66% - 1px),
          100% calc(66.66% - 1px),
          100% 100%,
          0% 100%
        );
      }
    }
  }
}

JavaScript

const tl = gsap.timeline({
  repeat: -1,
  defaults: {
    ease: "power2.inOut",
    duration: 1.2,
  },
});

tl.fromTo(
  ".js-flip--kv1 .js-flip-part--top",
  {
    clipPath:
      "polygon(0% 0%, 100% 0%, 100% calc(33.33% + 1px), 0% calc(33.33% + 1px))",
  },
  {
    clipPath:
      "polygon(0% 0%, 0% 0%, 0% calc(33.33% + 1px), 0% calc(33.33% + 1px))",
  },
  "+=1.5",
);

tl.fromTo(
  ".js-flip--kv1 .js-flip-part--middle",
  {
    clipPath:
      "polygon(0% calc(33.33% - 1px), 100% calc(33.33% - 1px), 100% calc(66.66% + 1px), 0% calc(66.66% + 1px))",
  },
  {
    clipPath:
      "polygon(100% calc(33.33% - 1px), 100% calc(33.33% - 1px), 100% calc(66.66% + 1px), 100% calc(66.66% + 1px))",
  },
  "<",
);

tl.fromTo(
  ".js-flip--kv1 .js-flip-part--bottom",
  {
    clipPath:
      "polygon(0% calc(66.66% - 1px), 100% calc(66.66% - 1px), 100% 100%, 0% 100%)",
  },
  {
    clipPath:
      "polygon(0% calc(66.66% - 1px), 0% calc(66.66% - 1px), 0% 100%, 0% 100%)",
  },
  "<",
);

tl.fromTo(
  ".js-flip--kv2 .js-flip-part--top",
  {
    clipPath:
      "polygon(0% 0%, 100% 0%, 100% calc(33.33% + 1px), 0% calc(33.33% + 1px))",
  },
  {
    clipPath:
      "polygon(0% 0%, 0% 0%, 0% calc(33.33% + 1px), 0% calc(33.33% + 1px))",
  },
  "+=2",
);

tl.fromTo(
  ".js-flip--kv2 .js-flip-part--middle",
  {
    clipPath:
      "polygon(0% calc(33.33% - 1px), 100% calc(33.33% - 1px), 100% calc(66.66% + 1px), 0% calc(66.66% + 1px))",
  },
  {
    clipPath:
      "polygon(100% calc(33.33% - 1px), 100% calc(33.33% - 1px), 100% calc(66.66% + 1px), 100% calc(66.66% + 1px))",
  },
  "<",
);

tl.fromTo(
  ".js-flip--kv2 .js-flip-part--bottom",
  {
    clipPath:
      "polygon(0% calc(66.66% - 1px), 100% calc(66.66% - 1px), 100% 100%, 0% 100%)",
  },
  {
    clipPath:
      "polygon(0% calc(66.66% - 1px), 0% calc(66.66% - 1px), 0% 100%, 0% 100%)",
  },
  "<",
);

tl.set(".js-flip--kv1 .js-flip-part--top", {
  clipPath:
    "polygon(0% 0%, 100% 0%, 100% calc(33.33% + 1px), 0% calc(33.33% + 1px))",
});

tl.set(
  ".js-flip--kv1 .js-flip-part--middle",
  {
    clipPath:
      "polygon(0% calc(33.33% - 1px), 100% calc(33.33% - 1px), 100% calc(66.66% + 1px), 0% calc(66.66% + 1px))",
  },
  "<",
);

tl.set(
  ".js-flip--kv1 .js-flip-part--bottom",
  {
    clipPath:
      "polygon(0% calc(66.66% - 1px), 100% calc(66.66% - 1px), 100% 100%, 0% 100%)",
  },
  "<",
);

tl.set(
  ".js-flip--kv1",
  {
    zIndex: 1,
  },
  "<",
);

tl.fromTo(
  ".js-flip--kv3 .js-flip-part--top",
  {
    clipPath:
      "polygon(0% 0%, 100% 0%, 100% calc(33.33% + 1px), 0% calc(33.33% + 1px))",
  },
  {
    clipPath:
      "polygon(0% 0%, 0% 0%, 0% calc(33.33% + 1px), 0% calc(33.33% + 1px))",
  },
  "+=2",
);

tl.fromTo(
  ".js-flip--kv3 .js-flip-part--middle",
  {
    clipPath:
      "polygon(0% calc(33.33% - 1px), 100% calc(33.33% - 1px), 100% calc(66.66% + 1px), 0% calc(66.66% + 1px))",
  },
  {
    clipPath:
      "polygon(100% calc(33.33% - 1px), 100% calc(33.33% - 1px), 100% calc(66.66% + 1px), 100% calc(66.66% + 1px))",
  },
  "<",
);

tl.fromTo(
  ".js-flip--kv3 .js-flip-part--bottom",
  {
    clipPath:
      "polygon(0% calc(66.66% - 1px), 100% calc(66.66% - 1px), 100% 100%, 0% 100%)",
  },
  {
    clipPath:
      "polygon(0% calc(66.66% - 1px), 0% calc(66.66% - 1px), 0% 100%, 0% 100%)",
  },
  "<",
);

tl.set(".js-flip--kv1 .js-flip-part--top", {
  clipPath:
    "polygon(0% 0%, 100% 0%, 100% calc(33.33% + 1px), 0% calc(33.33% + 1px))",
});
tl.set(
  ".js-flip--kv1 .js-flip-part--middle",
  {
    clipPath:
      "polygon(0% calc(33.33% - 1px), 100% calc(33.33% - 1px), 100% calc(66.66% + 1px), 0% calc(66.66% + 1px))",
  },
  "<",
);
tl.set(
  ".js-flip--kv1 .js-flip-part--bottom",
  {
    clipPath:
      "polygon(0% calc(66.66% - 1px), 100% calc(66.66% - 1px), 100% 100%, 0% 100%)",
  },
  "<",
);

tl.set(
  ".js-flip--kv1",
  {
    zIndex: 4,
  },
  "<",
);

コメント