tl;dr
- SVG独自の数値プロパティのインターフェイスが面白い
- 普段は Snap.svg か D3.js 使えばいいと思う
-
setAttribute
とのベンチマーク取ってない
SVGのプログラミング
普段JavaScriptでSVGを扱う場合、Snap.svgやD3.jsを利用することで事足りたり、もしくはReactで構築したりすることが最近は多いと思う。
なので滅多にないと思うけど、依存性の少ないライブラリやモジュールなどを書く場合の参考にと思って、プレーンなJavaScript(VanillaJS)の書き方を、ちょっとマニアックだけどフロントエンドエンジニアのアドベントカレンダーに記しておく。
名前空間
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
http://www.w3.org/2000/svg
が名前空間となる。createElement
ではなくcreateElementNS
を使う。
SVGAnimatedLengthインターフェイス
<svg>
要素(SVGSVGElement
インターフェイス)をはじめとするSVG関連の要素は、width
や height
などを属性を持つモノがいくつかあるが(<rect>``<image>``<pattern>
など)、HTMLのそれとは大きくインターフェイスが異なる。
HTMLElement
のwidth
やheight
のインターフェイスはDOMString
なので、次の例のように文字列をそのまま代入するこができる。
// `<img>`要素の例
const img = document.createElement('img');
img.width = '100%';
img.height = '100px';
一方、SVGの要素の場合、width
やheight
はSVGAnimatedLength
という馴染みのないインターフェイスで、しかも readonly なプロパティである。さらにSVGAnimatedLength
はbaseVal
とanimVal
というreadonlyなSVGLength
インターフェイスのプロパティをもち、newValueSpecifiedUnits
というメソッドで数値を変更することができる。第一引数は単位を指定する。
svg.width.baseVal.newValueSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_PERCENTAGE, 100);
svg.height.baseVal.newValueSpecifiedUnits(SVGLength.SVG_LENGTHTYPE_PX, 100);
もしくは valueAsString
に代入でもできる。
svg.width.baseVal.valueAsString = '100%';
svg.height.baseVal.valueAsString = '100px';
setAttribute
でも可能
HTMLのDOMと同様にsetAttribute
メソッドを持っているので、それを使って指定することも可能。
svg.setAttribute('width', '100%');
svg.setAttribute('height', '100px');
ベンチマーク / 利点
とっていない。
ので近々とってみる予定。
なんとなーく、微々たる差で、直接的なアクセスと単位のパース分でnewValueSpecifiedUnits
が早そう。SVGAnimatedLength
の利点はどちらかというとanimVal
にある気がするが、具体的にどういうプログラムで効果的なのかはわかっていない。来年ももっとSVGを使う機会が増えるだろうから、もっと掘り下げてみたい。