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

ローディング中に 3 つの点が順に跳ねる

デモ

仕様

動作
DOM
種類
レシピ
動作確認
three 0.186.0・gsap 3.15.0
公開日

しくみと調整

3 つの点を横に並べ、左から順に 1 つずつ跳ね上げて戻します。跳ねているあいだだけ点の色が変わるので、小さな点でもどこが動いているかを読み取れます。3 つが跳ね終わったら少し間を置いて、また左から繰り返します。

上りは 0.3 秒の power2.out で、隣の点とは 0.12 秒ずらします。上りを減速にすると、往復の折り返しで下りが加速に変わり、落ちて着地したように見えます。跳ねる高さは点の直径の 1.3 倍、次の周までの間は 0.46 秒です。この間を詰めると、待っている人を急かす速さになります。

往復の指定(yoyorepeat)は、必ず stagger の中に書きます。外に書くと、3 つがまとめて上がってまとめて下りる 1 つの動きになり、順に跳ねる形がそのまま消えます。

読み込みが終わったときに抜ける口を、最初に作っておきます。終わりを知らせる関数を 1 つ用意し、その中で繰り返しを止めて要素を取り除けば、読み込みが済んだのに点だけ回り続けることがありません。画面には出さない「読み込み中」の一文を添えておくと、読み上げにも待っていることが伝わります。

点の数を増やしても、ずらす間隔を変えるだけで同じ形を保てます。終わりの見当が付かない待ち時間に向いていて、送信の待ち、一覧の読み込み、ページの切り替えなどに使えます。受け取った量が数で分かるものは、進み具合を出す表示のほうが待ちやすくなります。

コード

HTML
<div class="dots-loader" role="status">
  <span class="dots-loader__dot"></span>
  <span class="dots-loader__dot"></span>
  <span class="dots-loader__dot"></span>
  <span class="dots-loader__text">読み込み中</span>
</div>
CSS
.dots-loader {
  --dot: 14px;        /* 点の直径 */
  --gap: 10px;        /* 点の間 */
  --ink: #262626;     /* 休んでいる点の色 */
  --jump: #ff5a1f;    /* 跳ねているあいだの点の色 */
  --ground: #f2f1ed;  /* 地の色 */
  position: fixed;
  inset: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap);
  background: var(--ground);
}

.dots-loader__dot {
  width: var(--dot);
  height: var(--dot);
  border-radius: 50%;
  background: var(--ink);
}

/* 読み上げにだけ届く文言。画面には出さない */
.dots-loader__text {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
JavaScript
import { gsap } from "gsap";

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

function createLoader(root) {
  const dots = root.querySelectorAll(".dots-loader__dot");
  // 色と大きさは CSS が正。GSAP は var(--name) のままでは補間できないので、値にして渡す
  const jump = getComputedStyle(root).getPropertyValue("--jump").trim();
  const lift = dots[0].offsetHeight * 1.3;

  // yoyo と repeat は stagger の中に書く(外に書くと、3 つがまとめて往復する)。
  // repeatDelay は、跳ね終わってから次の周が始まるまでの間
  const bounce = gsap.timeline({ repeat: -1, repeatDelay: 0.46 }).to(dots, {
    y: reduceMotion ? 0 : -lift, // 動きを減らす設定では、色の変化だけで順番を見せる
    backgroundColor: jump,
    duration: 0.3,
    ease: "power2.out",
    stagger: { each: 0.12, yoyo: true, repeat: 1 },
  });

  return {
    // 読み込みが終わったら呼ぶ。呼ぶまで跳ね続ける
    done() {
      gsap.to(root, {
        autoAlpha: 0,
        duration: reduceMotion ? 0 : 0.3,
        onComplete: () => {
          bounce.kill();
          root.remove();
        },
      });
    },
  };
}

// 例: fetch や画像の読み込みを待って loader.done()
export const loader = createLoader(document.querySelector(".dots-loader"));

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

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