SVGつらい

スクリプトで操作しようとした時の罠の多さといったら。

<text strokeWidth="1" stroke="black" y="20" x="20">hoge</text>

のxをいじるのでも知らないと罠にハマる。
独自プロパティとかめんどくさかったら全部setAttribute使っとけばだいたいなんとかなるし以下も見る必要ない。
f:id:ebifly10:20141116225233p:plain

普通に書き換えようとしたら
f:id:ebifly10:20141116221644p:plain

あれ、x変わってない?

f:id:ebifly10:20141116221830p:plain

SVGAnimatedLengthList?誰だお前?
SVGAnimatedLengthList - Web API インターフェイス | MDN
多くのSVG関係のオブジェクトはアニメーション中の値と通常の値のanimValとbaseValに分かれてたりと隙あらば後ろから刺そうとしてくるこの感じ。

The SVGAnimatedLengthList interface is used for attributes of type SVGLengthList which can be animated.

Animatedとかいいつつ実態はSVGLengthListなのでドキュメントはそっちを参照することになる。
SVGLengthList - Web API Interfaces | MDN

f:id:ebifly10:20141116222301p:plain
こうして

text.x.baseVal.getItem(0).value

とvalueを見ることでやっと直に値を触れる。
ドットの数が非常に嫌な感じ。

別の方法としてSVGLengthをあれこれするのもあるけどこれもまためんどくさい。

まずどっかからsvgを取ってくる。なければ作る。

var svg = document.querySelector("svg");

そしてこのSVGにcreateSVGLengthメソッドがあるのでそれを使う。

var newX = svg.createSVGLength();

valueプロパティを書き換える。

newX.value = 40;

f:id:ebifly10:20141116223743p:plain
最後にSVGLengthListにはreplaceItemメソッドがあるのでそれを使う。
直接プロパティを着替えようとしてもだめ。

text.x.baseVal[0] = newX;

だめー。

f:id:ebifly10:20141116230046p:plain
おけー。

結論としては大人しくライブラリを使うか必死になって自作しないとしんどい。
SVG関係で参照する資料としては
svg要素の基本的な使い方まとめ
がすごい充実しているしブログと合わせて大抵の事は解決する。
もしくはMozilla
Web API インターフェイス | MDN
内のSVG-や、内容が限定されるけどMSDNも分かりやすい
SVG (Windows)

もし自力で頑張るのだとしてもこんなの作っとくだけでもだいぶ違う。

var SvgUtil = (function() {
    
    var namespace = "http://www.w3.org/2000/svg";
    
    var setAttributes = function(element, attributes) {
        
        Object.keys(attributes).forEach(function(key) {
           element.setAttribute(key, attributes[key]);
        });
    };
    
    var create = function(name, option) {
        var result = document.createElementNS(namespace, name);
        
        if(option !== void 0) {
            if(option.attributes) {
                setAttributes(result, option.attributes);
            }                       
        }        
        return result;
    };    
    
    return {
        create : create,
        setAttributes : setAttributes
    };
})();