本文へスキップ
HELLO!
HIGASHIYUKI®.COM
0   /   100
ヒーロー

ブロブが形と色を変えながら回る

デモ

仕様

用途
ヒーロー
動作
DOM
種類
レシピ
使うもの
MorphSVGPlugin
動作確認
three 0.186.0・gsap 3.15.0
公開日

しくみと調整

3 つのブロブの形を MorphSVGPlugin で順に変形し、色も一緒に移しながらゆっくり回ります。各区間の前半は形を保ち、後半だけで次の形へ移るので、変形が唐突に始まらず落ち着いて見えます。

回転は一定の速さのまま回し続け、変形だけに sine.inOut の ease をかけています。速さの異なる 2 つの動きを重ねることで、ただ回るだけよりも複雑な印象になります。

3 つ目の形を最初の形へつなぐと、途中で止めてもループの継ぎ目が目立ちません。形の数を増やす場合も、同じ考え方で最後を最初につなげば継ぎ目なく回せます。

つまみは形の数・1 つの形にとどまる時間・色です。地は生成りのままにしておくと、ブロブの色が引き立ちます。ヒーローの装飾やローディングの背景など、視線を集めたいが主役ではない場所に向いています。

コード

HTML
<section class="blob-hero">
  <!-- 絵は飾りなので、読み上げからは外す -->
  <svg class="blob-hero__art" viewBox="0 0 600 600" aria-hidden="true">
    <path class="blob-hero__shape"></path>
  </svg>
  <div class="blob-hero__copy">
    <p class="blob-hero__eyebrow">Studio</p>
    <h1 class="blob-hero__title">かたちは、<wbr>変わりつづける。</h1>
    <p class="blob-hero__lead">ここに説明文が入ります。</p>
  </div>
</section>

CSS
.blob-hero {
  --bg: #f2f1ed;
  --ink: #262626;
  --blob-1: #b27771; /* ブロブの色(形の順)。明るさを離すと、形が移るのが見分けやすい */
  --blob-2: #98b1c4;
  --blob-3: #4a5b66;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(24px, 6vw, 64px);
  padding: 96px clamp(24px, 7vw, 96px);
  background-color: var(--bg);
  color: var(--ink);
}

.blob-hero__art {
  display: block;
  width: 100%;
  max-width: 420px;
}

.blob-hero__eyebrow {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.blob-hero__title {
  margin: 24px 0 0;
  font-size: clamp(32px, 5vw, 56px);
  line-height: 1.1;
  letter-spacing: -0.02em;
  word-break: keep-all; /* 和文を語の途中で折らず、<wbr> の所で折り返す */
}

.blob-hero__lead {
  margin: 24px 0 0;
  max-width: 30em;
  font-size: 18px;
  line-height: 1.8;
}

@media (max-width: 640px) {
  .blob-hero { grid-template-columns: minmax(0, 1fr); }
}

JavaScript
import { gsap } from "gsap";
import { MorphSVGPlugin } from "gsap/MorphSVGPlugin";

gsap.registerPlugin(MorphSVGPlugin);

const STEP = 1.2; // 1 つの形にとどまってから次へ移るまでの時間(秒)
// 3 つのブロブ形。前半は形を保ち、後半で次の形へ移る。色は CSS の --blob-1〜3
const SHAPES = [
  "M300,90 C420,90 510,170 510,300 C510,430 420,510 300,510 C180,510 90,430 90,300 C90,170 180,90 300,90 Z",
  "M300,70 C450,110 540,200 500,330 C460,470 370,540 260,500 C130,460 60,380 90,250 C120,130 190,40 300,70 Z",
  "M320,110 C430,60 540,160 520,280 C500,420 430,520 300,520 C160,520 70,420 110,300 C140,200 200,150 320,110 Z",
];
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

document.querySelectorAll(".blob-hero__shape").forEach((blob) => {
  const css = getComputedStyle(blob);
  const fills = SHAPES.map((_, i) => css.getPropertyValue(`--blob-${i + 1}`).trim());
  blob.setAttribute("d", SHAPES[0]);
  blob.setAttribute("fill", fills[0]);

  if (reduceMotion) return; // 動きを減らす設定では、最初の形のまま止めておく

  const tl = gsap.timeline({ repeat: -1 });
  tl.fromTo(blob, { rotation: 0, svgOrigin: "300 300" }, { rotation: 360, svgOrigin: "300 300", duration: SHAPES.length * STEP, ease: "none" }, 0);
  SHAPES.forEach((_, i) => {
    const next = (i + 1) % SHAPES.length;
    tl.to(blob, { morphSVG: SHAPES[next], fill: fills[next], duration: STEP * 0.6, ease: "sine.inOut" }, i * STEP + STEP * 0.4);
  });
});

インタラクションデザインについて、
お気軽にご相談ください。

ここに並べているのは、Web サイトの中で動く UI のサンプルです。新しく作るサイトに組み込むことも、いま公開中のサイトに、ボタンやヒーロー、スクロールの演出だけを足すこともできます。設計から実装までの進め方はWeb サイト制作、端末ごとの見え方や表示速度の考え方はレスポンシブウェブサイトのページにまとめています。映像として作る動きをお探しの場合はモーショングラフィックスをご覧ください。