clip-pathで手書き風SVGアニメーション|スクロールのたびに再発火する実装方法

目次

この記事でわかること

  • clip-path を使ってSVG・画像を手書き風にアニメーションさせる方法
  • IntersectionObserver でスクロールのたびにアニメーションを再発火させる実装
  • どんな形の画像にも使い回せるシンプルな構成

完成サンプル

このように、スクロールする度に手書き風のアニメーションが発火します。

この方法について詳しく解説していきます。
(このサンプルは、ページ最後にも登場します。)

clip-path アニメーションとは?

clip-path はCSSのプロパティで、要素の表示領域を任意の形にクリッピング(切り抜き)できます。
この記事では、SVGの <path> の描画軌跡に沿って clip-path を動かすことで、まるで手で線を引いているような表示エフェクトを実現します。

ライブラリ不要・軽量・どんな形状の画像にも対応できるのが最大の特徴です。


Vivus.js との使い分け

同じ「手書き風SVGアニメーション」でも、目的によって適した手法が異なります。

手法向いているケース
clip-path(本記事)シンプルな形状、ライブラリ不要、使い回しを重視したい
Vivus.js複雑なパス構造、線が複数に分岐する、より精密な描画表現が必要

複雑な手書きアニメーションには Vivus.js が適しています。
→ 詳細はこちら:Vivus.jsでSVGをスクロールのたびに手書き風アニメーションを再生させる実装方法


仕組みの概要

  1. <img> タグで表示したい画像(SVGアイコンなど)を配置する
  2. 親要素 .js-line-animIntersectionObserver を設定する
  3. 画面内に入ったら .is-show クラスを付与し、外れたら削除する
  4. CSS でアニメーションを定義する

clip-path を使う最大のメリットは、SVGの内部構造に依存しないため、どんな形の画像でもそのまま使い回せる点です。パスの変換作業が不要で、PNGやSVGを差し替えるだけで動作します。


実装コード

CSS(SCSS)

// .js-line-anim  手書き風アニメーション
//始点を左→右にする場合
.js-line-anim {
  img {
    clip-path: inset(0 100% 0 0);
    transition: clip-path 0.7s ease 0.5s;
  }
  &.is-show img {
    clip-path: inset(0 0% 0 0);
  }

  //始点を右→左にする場合
  &--reverse {
    img {
      clip-path: inset(0 0 0 100%);
    }
    &.is-show img {
      clip-path: inset(0 0% 0 0);
    }
  }

  //始点を上→下にする場合
  &--down {
    img {
      clip-path: inset(0 0 100% 0);
    }
    &.is-show img {
      clip-path: inset(0 0% 0 0);
    }
  }
}

HTML

<span class="js-line-anim">
  <img
    src="この画像のパスを変えてください"
    alt=""
    width="100"
    height="100"
    loading="lazy"
  />
</span>

.js-line-animで画像を囲むだけの、シンプルな構成です。
画像を差し替えるだけで使い回しができます。


JavaScript

// .js-line-anim 手書き風スクロールアニメーション (clip-path)============
document.addEventListener("DOMContentLoaded", () => {
  const lineAnims = document.querySelectorAll(".js-line-anim");
  if (!lineAnims.length) return;

  const lineObserver = new IntersectionObserver(
    (entries) => {
      entries.forEach((entry) => {
        const el = entry.target;
        if (entry.isIntersecting) {
          el.classList.add("is-show");
        } else {
          if (entry.intersectionRatio === 0) {
            el.classList.remove("is-show");
          }
        }
      });
    },
    {
      threshold: [0, 0.3],
      rootMargin: "0px 0px -10% 0px",
    },
  );

  lineAnims.forEach((el) => lineObserver.observe(el));
});

コードのポイント解説

IntersectionObserver でスクロール検知
scroll イベントではなく IntersectionObserver を使うことで、パフォーマンスへの影響を最小限に抑えています。

スクロールのたびに再発火する仕組み
entry.intersectionRatio === 0(要素が完全に画面外に出たとき)に限り is-show クラスを削除しています。これにより、画面に入るたびにアニメーションがリセット・再生されます。

rootMargin: "0px 0px -10% 0px" について
ビューポートの下端から10%手前でアニメーションが発火するよう設定しています。値を調整することで、発火タイミングをコントロールできます。

threshold: [0, 0.3] について
0(完全に画面外)と 0.3(30%表示)の2段階を監視しています。is-show 付与は isIntersectingtrue になったタイミング、削除は intersectionRatio === 0 になったタイミングで行います。


完成サンプル

注意点・制限事項

このアプローチは シンプルで使い回しやすい反面、複雑なアニメーションには向いていません

  • 線が複数に枝分かれするような複雑な手書き表現には不向き
  • パスの描画順序を細かくコントロールしたい場合は Vivus.js が適切
  • clip-path のアニメーションはブラウザの対応状況に依存する(主要ブラウザは対応済み)

まとめ

clip-path を使った手書き風SVGアニメーションの実装ポイントをまとめます。

  • IntersectionObserver でスクロールのたびに再発火する仕組みを実現
  • clip-path を用いることでライブラリ不要・どんな画像でも対応可能
  • シンプルな構成なのでHTMLの <img> を差し替えるだけで使い回せる

複雑なSVGアニメーションには Vivus.js の活用もぜひ検討してみてください。
Vivus.jsで手書き風SVGアニメーションをスクロールのたびに再生させる方法


この記事が役に立ったら、ぜひシェアしてください!

WEBもがき道場

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
目次