こんにちは、Ryohei(@ityryohei)です!

SVG(Scalable Vector Graphics)は、Web上で高品質なベクターグラフィックを扱うためのXMLベースのフォーマットです。HTML内に直接記述できるため、JavaScriptによるDOM(Document Object Model)操作の対象となります。

静的なSVG図形に命を吹き込み、インタラクティブな Web 表現や高性能なアニメーションを実現するには、JavaScriptによるSVG要素の動的な操作が不可欠です。

本記事では、SVG要素の取得と属性の変更といった基本的なDOM操作から、SVG特有の座標系と変形の扱い、そしてJavaScriptを用いた滑らかなアニメーションの実装テクニックまでを、段階的に解説します。

SVGをJavaScriptで操作してみたいけど、HTML要素と同じように扱えるの?アニメーションの実装方法は?

上記の疑問にお答えします。

では、解説していきます。

1. SVG要素の基本操作:DOMとしてのSVG

SVGの各要素(<circle>, <rect>, <path>など)は、HTMLの<div><span>と同じようにDOMノードとして存在します。したがって、標準のDOM APIを使って要素の取得や操作が可能です。

1.1. 要素の取得と属性の変更

JavaScriptからSVG要素を取得する方法は、HTML要素と全く同じです。

  • document.getElementById()
  • document.querySelector()
  • document.querySelectorAll()

そして、要素の描画を変更する場合、styleプロパティを使うこともできますが、SVGではsetAttribute()メソッドを使ってSVG固有の属性(fill, r, xなど)を変更することが一般的です。

HTML

<svg id="chart-svg" width="300" height="150">
  <circle id="data-point" cx="50" cy="100" r="10" fill="teal" />
</svg>

JavaScript

const circle = document.getElementById('data-point');

// 属性の変更:色を青に、半径を20pxに拡大
circle.setAttribute('fill', 'blue');
circle.setAttribute('r', '20');

// 座標の変更
circle.setAttribute('cx', '150'); // X座標を50から150に移動

実行結果

See the Pen Untitled by ryohei (@intotheprogram) on CodePen.

1.2. 要素の動的な生成と追加

JavaScriptを使って新たなSVG要素を動的に生成し、既存のSVGコンテナ(<svg>タグ)に追加することで、データに基づくグラフなどを描画できます。

SVG要素を作成するには、document.createElementNS()を使います。通常のdocument.createElement()とは異なり、SVGの名前空間(Namespace)を指定する必要があります。

JavaScript

const svgNS = 'http://www.w3.org/2000/svg';
const svgContainer = document.getElementById('chart-svg');

// 新しい矩形(<rect>)要素をSVG名前空間で作成
const newRect = document.createElementNS(svgNS, 'rect');

newRect.setAttribute('x', '200');
newRect.setAttribute('y', '50');
newRect.setAttribute('width', '50');
newRect.setAttribute('height', '50');
newRect.setAttribute('fill', 'orange');

// SVGコンテナに追加
svgContainer.appendChild(newRect);

実行結果

See the Pen 8289-2 by ryohei (@intotheprogram) on CodePen.

2. SVG特有の変形:transform属性の操作

SVG要素の位置や回転、拡大縮小といった変形を行うには、CSSのtransformプロパティと似たSVG固有のtransform属性を使います。

2.1. 変形属性(transform)の基本構文

transform属性は、複数の変形関数をスペース区切りで記述します。

変形関数意味
translate(x, y)要素をX方向にx、Y方向にyだけ平行移動させる。
scale(s)要素をs倍に拡大・縮小させる。
rotate(angle)要素をangle度回転させる。

JavaScript

const rect = document.getElementById('my-rect'); 
// 矩形をX軸に50px移動し、45度回転させる
rect.setAttribute('transform', 'translate(50, 0) rotate(45)'); 

実行結果

See the Pen Untitled by ryohei (@intotheprogram) on CodePen.

2.2. 動的な変形:座標と値の計算

SVG要素をユーザーの操作や計算結果に基づいて動かすには、JavaScriptで変形値を計算し、それをtransform属性に動的に適用します。

例えば、円をマウスの位置に合わせて移動させるには、イベントリスナー内で計算を行います。

JavaScript

const circle = document.getElementById('data-point'); 

// マウス移動イベントにリスナーを設定
document.addEventListener('mousemove', (event) => {
    // 画面座標 (clientX, clientY) を取得
    const newX = event.clientX;
    const newY = event.clientY;
    
    // SVGの属性を更新して円を移動
    circle.setAttribute('cx', newX);
    circle.setAttribute('cy', newY);
});

実行結果

See the Pen 8389-3 by ryohei (@intotheprogram) on CodePen.

  • 補足:厳密には、画面座標をSVGのビューボックス座標に変換する処理が必要になる場合があります。

3. JavaScriptによる滑らかなSVGアニメーション

SVGアニメーションにはCSS AnimationやSMIL(非推奨)など複数の手法がありますが、JavaScriptを使うと、複雑なロジックやデータに基づいたより柔軟なアニメーション制御が可能です。

3.1. requestAnimationFrameの利用

滑らかなアニメーションを実現するための最善の方法は、ブラウザに最適化された描画サイクルに合わせて処理を行うrequestAnimationFrame (rAF) を利用することです。

rAFは、画面が更新される直前(通常は1秒間に60回、60fps)に関数を実行するため、ブラウザの負荷を抑え、カクつきのないアニメーションを実現します。

JavaScript

const rect = document.getElementById('my-rect'); 
let rotation = 0;

function animateRotation() {
    rotation += 2; // 角度を2度ずつ増加
    
    // transform属性を更新
    rect.setAttribute('transform', `rotate(${rotation}, 50, 50)`); // 50,50を中心に回転
    
    // 次のフレームで再度この関数を実行するようブラウザに要求
    requestAnimationFrame(animateRotation); 
}

// アニメーション開始
requestAnimationFrame(animateRotation); 

実行結果

See the Pen 8389-4 by ryohei (@intotheprogram) on CodePen.

3.2. イージング(Easing)の実装

アニメーションにリアルさや魅力を加えるためには、動きに緩急(イージング)をつけることが重要です。JavaScriptでは、時間の経過を表す0から1までの値(線形)を、緩急を示す別の値(非線形)に変換する計算関数(イージング関数)を自作または利用します。

JavaScript

// 例: イーズアウト関数 (最初速く、徐々に遅くなる)
function easeOutQuad(t) {
    return t * (2 - t);
}

// アニメーションループ内で使用
function animatePosition(timeFraction) {
    // timeFraction (0から1) をイージング関数に通す
    const progress = easeOutQuad(timeFraction); 
    
    // progressに基づいて位置を計算し、SVG属性に適用
    // ...
}

最後に

SVGをJavaScriptで操作することは、モダンなWebアプリケーションで高性能なグラフィック表現を行うための基本です。

  • 要素操作:setAttribute()を使ってSVG固有の属性を操作しましょう。
  • 変形:transform属性を使って、位置(translate)や回転(rotate)を制御しましょう。
  • アニメーション:requestAnimationFrame (rAF) を利用し、ブラウザに優しい滑らかなアニメーションを実現しましょう。

これらの基本操作とテクニックを習得することで、静的な図形をユーザーと対話する動的な表現へと進化させることができるでしょう。

以上、SVGの基本的な要素操作とアニメーション実装ガイドのご紹介でした!

この記事を書いた人

Ryohei

Webエンジニア / ブロガー

福岡のWeb制作会社に務めるWebエンジニアです。エンジニア歴は10年程で、好きな言語はPHPとJavaScriptです。本サイトは私がインプットしたWebに関する知識を整理し、共有することを目的に2015年から運営しています。Webに関するご相談があれば気軽にお問い合わせください。