以前、以下の SVG を使ったモーションパスを JavaScript で生成したかったので、色々調べてみて試した内容があり、それを記事にしてみます。
将来の自分へのメモも兼ねているので、見返しやすいようにシンプルな内容の記事にできればと思います。
今回扱う事例
JavaScript で SVG を動的に生成する話を書いていくのに、冒頭のモーションパスの例だと内容がシンプルにならなそうでした。
そのような中、最近書いた以下の記事は SVG の内容がシンプルなので、それを題材にしてみようと思います。
●p5.js で SVGフィルターを使う(p5.js Web Editor上の HTML・JavaScript に手を加えて利用) - Qiita
https://qiita.com/youtoy/items/217bfe7e940f2a7e2626
JavaScript で SVG を動的に生成する時のポイント(「createElementNS()」を使う)
冒頭に書いた、モーションパスの事例をあれこれ試していた当時、最初は createElement() を使って SVG を生成ようとしたのですが、それがうまくいかないという状況がありました。
そして試行錯誤や調査をした結果、SVG を動的に生成する場合は「createElementNS()」を使う必要がある、というのが分かり、その後は大きなハマりポイントもなく進められました。
なお、調べて参照した情報源は、こんな感じです。
- Creating SVG elements dynamically with javascript inside HTML - Stack Overflow
- JavaScript | createElementNSでSVGの図形を描画する基本 | ONE NOTES
- SVGをcreateElementするには「NS」が必要。
createElementNS() を使った SVG の動的な生成
p5.js Web Editor上で試す
タイトルにも書いたとおり、今回のお試しは「p5.js Web Editor上」で行います。
上で記載していた記事では、HTML の「</body>」の前に、以下のタグを直書きしていました。
この記事では、この SVG要素とその中身の部分を JavaScript で生成します。
<svg>
<filter id="feGaussianBlur">
<feGaussianBlur stdDeviation="10 3" />
</filter>
</svg>
その SVG の動的生成の処理は、以下の内容を p5.js Web Editor の「sketch.js」の「setup()」の中に書きました。
const parentnode = document.body;
const svgElt = document.createElementNS("http://www.w3.org/2000/svg", "svg");
parentnode.appendChild(svgElt);
svgFilter = document.createElementNS('http://www.w3.org/2000/svg', 'filter');
svgFilter.id = "feGaussianBlur";
svgElt.prepend(svgFilter);
const feGaussianBlur = document.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur');
feGaussianBlur.setAttribute("stdDeviation", "10 3");
svgFilter.prepend(feGaussianBlur);
1つ目のまとまりの処理で SVG要素を生成しています。
そして 2つ目のまとまりが、その1つ下の「filter」の部分で、最後のまとまりが「feGaussianBlur」になる形です。
また、上記の処理の後には、canvas要素に SVGフィルターを適用する処理を忘れず入れておきます。
以下に、描画処理なども合わせた「sketch.js全体の内容」を掲載します。
let canvas;
function setup() {
canvas = createCanvas(400, 300);
fill(100, 100, 150);
const parentnode = document.body;
const svgElt = document.createElementNS("http://www.w3.org/2000/svg", "svg");
parentnode.appendChild(svgElt);
svgFilter = document.createElementNS('http://www.w3.org/2000/svg', 'filter');
svgFilter.id = "feGaussianBlur";
svgElt.prepend(svgFilter);
const feGaussianBlur = document.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur');
feGaussianBlur.setAttribute("stdDeviation", "10 3");
svgFilter.prepend(feGaussianBlur);
canvas.style("filter", 'url(#feGaussianBlur)');
}
function draw() {
background(220);
circle((frameCount * 5) % width, frameCount % height, 50);
}
ちなみに、HTML は p5.js Web Editor のデフォルトの内容から、「p5.sound.min.js」の読み込みを削っただけの内容です。CSS(style.css)は、デフォルトの内容に何も手を加えていない、そのままの内容です。
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<main>
</main>
<script src="sketch.js"></script>
</body>
</html>
そして、p5.js Web Editor でプログラムを実行し、ブラウザの開発者ツールを使って処理結果を確認してみます。
そうすると、以下の画像のように SVG が動的に生成されているのが確認できました。
そして、p5.js Web Editor のプレビューでも、以下のように Blur が適用されているのが確認できました。
ちなみに動いている時の様子は、前の記事に掲載していた以下と全く同じになります。