この記事でわかること
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をスクロールのたびに手書き風アニメーションを再生させる実装方法
仕組みの概要
<img>タグで表示したい画像(SVGアイコンなど)を配置する- 親要素
.js-line-animにIntersectionObserverを設定する - 画面内に入ったら
.is-showクラスを付与し、外れたら削除する - 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 付与は isIntersecting が true になったタイミング、削除は intersectionRatio === 0 になったタイミングで行います。
完成サンプル
注意点・制限事項
このアプローチは シンプルで使い回しやすい反面、複雑なアニメーションには向いていません。
- 線が複数に枝分かれするような複雑な手書き表現には不向き
- パスの描画順序を細かくコントロールしたい場合は Vivus.js が適切
clip-pathのアニメーションはブラウザの対応状況に依存する(主要ブラウザは対応済み)
まとめ
clip-path を使った手書き風SVGアニメーションの実装ポイントをまとめます。
IntersectionObserverでスクロールのたびに再発火する仕組みを実現clip-pathを用いることでライブラリ不要・どんな画像でも対応可能- シンプルな構成なのでHTMLの
<img>を差し替えるだけで使い回せる
複雑なSVGアニメーションには Vivus.js の活用もぜひ検討してみてください。
→ Vivus.jsで手書き風SVGアニメーションをスクロールのたびに再生させる方法
この記事が役に立ったら、ぜひシェアしてください!
