Blog スタッフブログ

【GSAP】どんなSVGでも破綻しないラインアニメーションを実装しよう

Category | Blog
Tag |
/ 23views

こんにちは、ウィルスタイルの梁川です。

入社から早くも5ヶ月が経ち、毎日多くの学びがある日々を送っています。
既存サイトの保守・更新や下層ページのデザイン、ディレクションの補助など、さまざまな業務を経験させていただき、時間が経つのもあっという間です。

どの業務も楽しんでいますが、個人的な関心としてWeb上でのアニメーションを探求するのが好きです。

今回は、スクロールに合わせて線が描かれるSVGアニメーションの作り方をご紹介したいと思います。
視線誘導やストーリー性を作るうえで、とても効果的な表現です。

実際の挙動や全体のコードは、以下のURLからご確認いただけます。

Table of contents

  1. HTML・CSS
  2. 線が描かれる仕組み
  3. JavaScriptでの実装
  4. 完成アニメーション
  5. おわりに

HTML・CSS

まずは土台となるコードです。いくつかこだわっているポイントだけピックアップします。

HTML
<div class="circle__item">
	<svg class="circle__shape" data-circle aria-hidden="true" ...>
		<path stroke="#000" d="..." />
	</svg>
</div>

HTMLでは、JavaScriptのフック用に data-circle というデータ属性を使用しました。クラス名(スタイル用)と分けることで、デザイン変更に強い設計にしています。
また、装飾用の画像なので aria-hidden="true" を付与し、スクリーンリーダーへの配慮も行っています。

CSS
.circle__item {
	margin-top: -180px;
}

CSSでは、margin-top にマイナスの値を指定して円の要素を重ねて、連鎖する波紋のような奥行きを表現しました。

線が描かれる仕組み

実装に入る前に、そもそもなぜ線が伸びていくように見えるのか、その原理を整理しておきましょう。
これは、線を伸ばしているのではなく、点線の隙間を移動させているというイメージです。

鍵となるのは、SVGの2つのプロパティです。

  • stroke-dasharray:点線の「実線」と「隙間」の間隔
  • stroke-dashoffset:線の開始位置のズレ

アニメーションの原理

通常、点線は「実線・隙間・実線…」の繰り返しですが、「実線の長さ」と「隙間の長さ」を、パスの全長と同じ長さに設定することで、今回のようなアニメーションが実装できます。

  1. 隠す(初期状態)
    stroke-dasharray で「全長分の実線」と「全長分の隙間」を作ります。
    そして stroke-dashoffset を使って、開始位置を「全長分」ずらします。
    そうすると、画面上では「隙間」の部分だけが表示され、線が見えなくなります。
  2. 描く(アニメーション)
    スクロールに合わせて、ずらしていた stroke-dashoffset0 に戻していきます。
    すると、画面外に押し出されていた「実線」の部分が入ってきて、線が描かれているように見せることができます。

JavaScriptでの実装

仕組みがわかったところで、今回のメインであるJavaScriptの実装です。

Step 1:要素の取得とループ処理

const circles = document.querySelectorAll("[data-circle]");

if (circles.length > 0) {
	circles.forEach((el) => {
		const path = el.querySelector("path");
		if (!path) return; // エラー回避
	});
}

まず querySelectorAll で対象となるSVGをすべて取得します。
その後、forEach を使って1つずつ処理を回していきます。こうすることで、ページ内に複数のアニメーションがあっても、それぞれ個別に動作させることができます。
if (!path) return; は、万が一SVG内にパスが含まれていなかった場合にエラーで止まるのを防ぐための記述です。

Step 2:パスの長さを自動取得

// パスの正確な長さを取得
const length = path.getTotalLength();

ここが今回の最大のポイントで、 getTotalLength() メソッドを使うと、パスの正確な幾何学的な長さを取得できます。
これにより、「SVGを差し替えたら線が足りなくなる」といった問題を解消できます。

Step 3:初期状態のセット(線を隠す)

gsap.set(path, {
	strokeDasharray: length,
	strokeDashoffset: length
});

取得した length を使って、CSSプロパティをセットします。
gsap.set で初期状態を指定します。
ここで「線の長さ」と「ズレ」をどちらも全長と同じにすることで、画面上では線が完全に隠れた状態になります。

Step 4:スクロールアニメーションの設定

gsap.to(path, {
	strokeDashoffset: 0, // 0に戻して線を描く
	ease: "none",
	scrollTrigger: {
		trigger: el,
		start: "top center",
		end: "center center",
		scrub: 1,
	}
});

最後に gsap.to でアニメーションを実行します。
strokeDashoffset0 に戻すことで、隠れていた実線部分が画面内に引き戻され、線が描かれていきます。

  • ease: “none”
    デフォルトの「動き出しがゆっくり」などのイージングを解除し、スクロールと等速で描かれるようにします。
  • scrub: 1
    スクロールに追従させます。true ではなく数値を指定することで、ピタッと止まらず「1秒遅れて追いつく」ような余韻が生まれ、リッチな操作感になります。

完成アニメーション

完成したものがこちらです。
正確な長さを取得しているため、最後まで気持ちよく線が描かれています。

円形以外のSVGにも差し替えてみました。 コードの変更は一切なく、HTMLのSVGタグを変えただけで、このように複雑な波線もきれいに描画されます。

おわりに

いかがだったでしょうか。
今回は「getTotalLength」を活用して、メンテナンス性の高いSVGラインアニメーションを実装しました。
一度仕組みを作ってしまえば、ロゴや手書き文字など、あらゆるSVGアニメーションに応用が効きます。ぜひプロジェクトに取り入れてみてください。

Category | Blog
Tag |
Author | Takuma Yanagawa / 23views

Company information

〒650-0024
神戸市中央区海岸通5 商船三井ビルディング4F

Contact us

WEBに関するお問い合わせは
078-977-8760 (10:00 - 18:00)