本文へスキップ
HELLO!
HIGASHIYUKI®.COM
0   /   100
ローディング

ローディング中にロゴマークを線で描いてから塗る

デモ

仕様

動作
DOM
種類
レシピ
使うもの
DrawSVGPlugin
動作確認
three 0.186.0・gsap 3.15.0
公開日

しくみと調整

抽象的なロゴマークを、輪から 3 枚の葉の順に線で描いていきます。描き終えた部分は面の塗りに置き換わり、線が消えていくので「線から面へ」動いているように見えます。塗り終えると全体が軽く弾み、最後は縮んで消えます。

輪を描くのに 0.9 秒、3 枚の葉は 0.12 秒ずつずらしながら 0.8 秒で描きます。線から面への切り替えは 0.45 秒で、線がすべて消えると同時に塗りが完成します。始まりと終わりはどちらも何も見えていない状態なので、そのままループにつながります。

縮めて消す動きは、葉ごとの中心ではなく輪全体の中心に向けて縮めないと、それぞれの葉が別々の方向に消えていく不自然な見え方になります。動きを減らす設定では、線を描く動きをやめて塗った状態のまま明るさだけをゆっくり明滅させ、大きな動きを見せません。

色や形をロゴに合わせて差し替えれば、そのままブランドのローディング表示として使えます。読み込みが終わったら塗り終えた時刻で止めれば、マークが完成した姿でページに引き継げます。

コード

HTML
<div class="logo-loader" role="status">
  <svg class="logo-loader__svg" viewBox="-100 -100 200 200" aria-hidden="true">
    <g class="logo-loader__mark">
      <circle class="logo-loader__ring" cx="0" cy="0" r="92" transform="rotate(-90)" />
      <g transform="rotate(0)"><path class="logo-loader__leaf logo-loader__leaf--1" d="M0,-8 C-30,-26 -30,-58 0,-78 C30,-58 30,-26 0,-8 Z" /></g>
      <g transform="rotate(120)"><path class="logo-loader__leaf logo-loader__leaf--2" d="M0,-8 C-30,-26 -30,-58 0,-78 C30,-58 30,-26 0,-8 Z" /></g>
      <g transform="rotate(240)"><path class="logo-loader__leaf logo-loader__leaf--3" d="M0,-8 C-30,-26 -30,-58 0,-78 C30,-58 30,-26 0,-8 Z" /></g>
    </g>
  </svg>
  <span class="logo-loader__text">読み込み中</span>
</div>

CSS
.logo-loader {
  --size: 216px;      /* マークの大きさ */
  --ground: #111111;  /* 地の色(Night) */
  --line: #EEECE6;    /* 線と 3 枚目の葉の色 */
  --leaf1: #788b97;   /* 1 枚目の葉(墨のスレート) */
  --leaf2: #d2b999;   /* 2 枚目の葉(グレージュ) */
  position: fixed;
  inset: 0;
  z-index: 10;
  display: grid;
  place-items: center;
  background: var(--ground);
}

.logo-loader__svg {
  width: var(--size);
  height: var(--size);
  overflow: visible;
}

.logo-loader__ring {
  fill: none;
  stroke: var(--line);
  stroke-width: 3;
}

.logo-loader__leaf {
  fill-opacity: 0;
  stroke: var(--line);
  stroke-width: 3.5;
  stroke-linejoin: round;
}

.logo-loader__leaf--1 { fill: var(--leaf1); }
.logo-loader__leaf--2 { fill: var(--leaf2); }
.logo-loader__leaf--3 { fill: var(--line); }

.logo-loader__text {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

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

gsap.registerPlugin(DrawSVGPlugin);

const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

function createLoader(root) {
  const ring = root.querySelector(".logo-loader__ring");
  const leaves = root.querySelectorAll(".logo-loader__leaf");
  const mark = root.querySelector(".logo-loader__mark");
  const draw = gsap.timeline({ repeat: -1 });

  if (reduceMotion) {
    // 線を描く動きをやめ、塗った状態のまま明るさだけをゆっくり明滅させる
    gsap.set(ring, { drawSVG: "100%" });
    gsap.set(leaves, { drawSVG: "100%", fillOpacity: 1, strokeOpacity: 0 });
    draw.to(mark, { opacity: 0.5, duration: 1.1, ease: "sine.inOut", yoyo: true, repeat: -1 });
  } else {
    // 輪 → 葉の順に線で描き、塗りを出しながら葉の線を消して「線 → 面」に移す
    draw
      .fromTo(ring, { drawSVG: "0%" }, { drawSVG: "100%", duration: 0.9, ease: "power2.inOut" }, 0.1)
      .fromTo(leaves, { drawSVG: "0%" }, { drawSVG: "100%", duration: 0.8, ease: "power2.inOut", stagger: 0.12 }, 0.35)
      .fromTo(leaves, { fillOpacity: 0, strokeOpacity: 1 }, { fillOpacity: 1, strokeOpacity: 0, duration: 0.45, ease: "power1.inOut", stagger: 0.1 }, 1.25)
      .fromTo(mark, { scale: 1, svgOrigin: "0 0" }, { scale: 1.06, svgOrigin: "0 0", duration: 0.2, ease: "power2.out", yoyo: true, repeat: 1 }, 1.6)
      .fromTo(ring, { drawSVG: "0% 100%" }, { drawSVG: "100% 100%", duration: 0.6, ease: "power2.in" }, 2.3)
      .fromTo(leaves, { scale: 1, svgOrigin: "0 0" }, { scale: 0, svgOrigin: "0 0", duration: 0.5, ease: "back.in(1.7)", stagger: 0.08 }, 2.4);
  }

  return {
    // 読み込みが終わったら呼ぶ
    done() {
      gsap.to(root, {
        autoAlpha: 0,
        duration: reduceMotion ? 0 : 0.3,
        onComplete: () => {
          draw.kill();
          root.remove();
        },
      });
    },
  };
}

export const loader = createLoader(document.querySelector(".logo-loader"));

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

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