お見受けする限り
<svg>
<g>...</g>
<g transform="...">...</g>
・
・
</svg>
という「svg要素下に複数のg要素がある」構造になるのですね?
ここでポイントなのが
- svg要素にviewBoxの指定が無ければ、暗黙的にsvg要素のwidth,heightがviewBoxに指定される
- viewBoxは読んで時の如く「表示領域」=ここをはみ出した範囲は可視できなくなる
- transform属性での指定の際、Matrixでは変形の中心を指定できない(rotateでの変形なら指定可)
- ただし、rotateで回転を中心点に指定しても2.の理由から上へはみ出した分は欠ける
- じゃあsvg要素にpadding指定すれば => 現状ブラウザの解釈の違いアリ(不安定)
また、matrixにscale
,skewX
,skewY
の指定も入っていますが、これもg要素毎に違うと考えるべきですよね?
となるとcreateSVGMatrix()でmatrixの指定を取得しても、skewで歪ませた分の位置を計算するのはちょっと面倒かなと思います。なので、ちょっと泥臭いですが、各要素の位置とサイズを取得して平均を出すという方法で
<svg id="svg"><!-- idを付与 -->
<g class="path"><!-- classを付与 -->
<path d="M50.00,0 L35.30,35.30 L0,39.70 L26.50,64.70 L20.60,100.00 L50.00,85.30 L79.40,100.00 L73.50,64.70 L100.00,39.70 L64.70,35.30 L50.00,0 z" />
<rect width="100" vector-effect="non-scaling-stroke" stroke-width="0.5" stroke="#000" height="100" fill="none" />
</g>
<g class="path" transform="matrix(2.82843 2.82843 -2.82843 2.82843 675.59 109.905)"><!-- classを付与 -->
<path d="M50.00,0 L35.30,35.30 L0,39.70 L26.50,64.70 L20.60,100.00 L50.00,85.30 L79.40,100.00 L73.50,64.70 L100.00,39.70 L64.70,35.30 L50.00,0 z" />
<rect width="100" vector-effect="non-scaling-stroke" stroke-width="0.5" stroke="#000" height="100" fill="none" />
</g>
</svg>
<script>
function getPos(el){
var rect = el.getBoundingClientRect();
return rect;
}
var element = document.getElementById('svg')
var childs = element.getElementsByTagName('g');
var childsLg = childs.length;
var pos = [];
for( var i=0; i<childsLg; i++ ){
//各g要素の位置とサイズを配列へ格納
pos[i] = getPos(childs[i]);
}
//1.ここで返ってきたx座標、y座標、width,heightを元に縦軸の平均値を計算
//2.1の値を元に全g要素に対してMatrixのtranslateを再設定
//IE対応も考えて、親のsvg要素へwidth,height再指定(※必要であれば。IEではwidth,heightを指定していなければ、ブラウザデフォルトで設定されてるサイズに固定される)
</script>
といった方法になるのかな…と。
もっと簡単にしたい場合
Matrixで指定することに拘らず、図形を1つのsvg要素内でまとめることに拘らないなら
Html
1<svg class="foo">
2 <g>...</g>
3</svg>
4<svg class="bar">
5 <g transform="...">...</g>
6</svg>
のようにして、cssでtransformを行えばtransform-originの指定なども効くので簡単かなと思います。