本文へスキップ
HELLO!
HIGASHIYUKI®.COM
0   /   100
アイコン

再生と一時停止のアイコンが形を変えて切り替わる

デモ

操作:クリック。 「さわってみる」を押すと自動再生が止まり、マウスで動かせます。

仕様

用途
アイコン
動作
DOM
種類
レシピ
使うもの
MorphSVGPlugin
動作確認
three 0.186.0・gsap 3.15.0
公開日

しくみと調整

再生の三角を、縦の割れ目で左右 2 枚の四角形に分けて描きます(右の 1 枚は、先端で 2 点を重ねた四角形です)。押すと、2 枚がそれぞれ一時停止の棒へ形を変え、三角が縦に割れて棒が起き上がるように見えます。もう一度押すと、同じ動きを逆にたどって三角に戻ります。

変形は MorphSVGPlugin で、0.45 秒の power3.inOut です。4 つの形の点の順を、左上 → 右上 → 右下 → 左下にそろえ、shapeIndex を 0 にして、点をそのまま対応させます。自動の対応に任せると、点の組み合わせがずれて、形がねじれながら変わることがあります。

角は、塗りと同じ色の線(幅 2・角は丸)を重ねて丸めます。線は形の外側へ 1 ずつ太るので、形はそのぶん小さく描いておきます。

切り替えは、ボタンの click ではなく、audio の play と pause のイベントで行います。最後まで再生して止まったときも、アイコンの形がそろいます。ボタンの名前も「再生」と「一時停止」で書き換えます。

このデモでは、再生中にジャケットの後ろへ光をにじませ、イコライザーの棒を揺らしています。時間と ease、三角の割れ目の位置、棒の幅と間隔で印象が変わります。音楽やポッドキャスト、動画のプレーヤー、スライドショーの自動再生の切り替えに向いています。

コード

HTML
<div class="player">
  <!-- 音源はサイトのものに差し替える -->
  <audio class="player__audio" src="/audio/sample.mp3" preload="metadata"></audio>
  <!-- 名前(aria-label)は、押したら何が起きるかを書く。script.js が「再生」と「一時停止」を入れ替える -->
  <button class="player__toggle" type="button" aria-label="再生">
    <svg class="player__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
      <!-- 三角を左右 2 枚の四角形に割る(右は先端で 2 点を重ねる)。点の順は、左上 → 右上 → 右下 → 左下 -->
      <path class="player__left" d="M8 6.5 L13 9.25 L13 14.75 L8 17.5 Z" />
      <path class="player__right" d="M13 9.25 L18 12 L18 12 L13 14.75 Z" />
    </svg>
  </button>
</div>

CSS
.player__toggle {
  --size: 48px;       /* ボタンの直径 */
  --icon: 24px;       /* アイコンの大きさ */
  --ground: #eeece6;  /* 丸の色(暗い地に置く明るい主ボタン) */
  --ink: #111111;     /* アイコンの色 */
  display: inline-grid;
  place-items: center;
  width: var(--size);
  height: var(--size);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background-color: var(--ground);
  color: var(--ink);
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

/* 塗りと同じ色の線(幅 2・角は丸)を重ねて、角を丸める。見た目は四方に 1 ずつ太る */
.player__icon {
  width: var(--icon);
  height: var(--icon);
  overflow: visible;
  fill: currentColor;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linejoin: round;
}

.player__toggle:focus-visible {
  outline: 2px solid var(--ground);
  outline-offset: 4px;
}

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

gsap.registerPlugin(MorphSVGPlugin);

const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
// 一時停止の 2 本の棒。点の順を三角の 2 枚とそろえてあるので、shapeIndex: 0 でそのまま対応させる
const PAUSE_LEFT = "M7 6 L9.5 6 L9.5 18 L7 18 Z";
const PAUSE_RIGHT = "M14.5 6 L17 6 L17 18 L14.5 18 Z";

document.querySelectorAll(".player").forEach((player) => {
  const audio = player.querySelector(".player__audio");
  const button = player.querySelector(".player__toggle");
  const left = button.querySelector(".player__left");
  const right = button.querySelector(".player__right");

  // 三角 → 2 本の棒。止めるときは同じタイムラインを逆再生する
  const toggle = gsap
    .timeline({ paused: true })
    .to(left, { morphSVG: { shape: PAUSE_LEFT, shapeIndex: 0 }, duration: 0.45, ease: "power3.inOut" }, 0)
    .to(right, { morphSVG: { shape: PAUSE_RIGHT, shapeIndex: 0 }, duration: 0.45, ease: "power3.inOut" }, 0);

  // 動きを減らす設定では、ほぼ一瞬で切り替える
  if (reduceMotion) toggle.timeScale(20);

  // 読み込めずに再生が始まらなかったときは、play が起きないので形も変わらない
  button.addEventListener("click", () => (audio.paused ? audio.play().catch(() => {}) : audio.pause()));

  // 最後まで再生して止まったときも形がそろうよう、ボタンではなく audio のイベントで切り替える
  audio.addEventListener("play", () => {
    toggle.play();
    button.setAttribute("aria-label", "一時停止");
  });
  audio.addEventListener("pause", () => {
    toggle.reverse();
    button.setAttribute("aria-label", "再生");
  });
});

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

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