Zythyr
Zythyr

Reputation: 1212

How can I translate SVG group element to the center of the root SVG?

Question: How can I translate the center of a SVG group element to the center of the root SVG. I tried to use transform="translate(x,y)" on the <g> element, but this transformation will only translate with respect to the top left corner of the group element.

Example case and goal: In the following SVG, the two rectangles <rect> are grouped together with <g>. Assume we don't know the position, size, and which types are elements are inside the group. We only know the width/height of the parent SVG. Goal is to translate the center of the group (bounding box of the two rectangles) to the center of the root SVG. The issue is that we don't know the height/width of the "bounding box" which is the group itself, thus when using transform="translate(x,y)" alone won't get us to the center of the root SVG.

<svg width="500px" height="300px" preserveAspectRatio="none" viewBox="0,0,5.0,3.0">
    <g transform="translate(0,0)">
        <rect x="1" y="0.25" width="0.5" height="0.5" fill="green" />
        <rect x="1.25" y="1" width="0.5" height="0.5" fill="red" />
    </g>
</svg>

Requirements:

enter image description here

Upvotes: 3

Views: 6592

Answers (1)

enxaneta
enxaneta

Reputation: 33064

You need some way to do calculations. I'm using Javascript:

const SVG_NS = 'http://www.w3.org/2000/svg';
const svg = document.querySelector("svg");
// the viewBox of the svg element splited
let svgVB = svg.getAttribute("viewBox").split(/[ ,]+/);


let o = test.getBBox();
let oCenter = {};//the center of the g#test element
oCenter.x = o.x + o.width/2;
oCenter.y = o.y + o.height/2;

// the valuefor the transform attribute
let tr = `
translate(${-oCenter.x},${-oCenter.y})
translate(${svgVB[2]/2},${svgVB[3]/2})`;


test.setAttributeNS(null, "transform",tr);


// for debugging I'm drawing the bounding box 
bbox.setAttributeNS(null, "transform",tr);

function drawRect(o, parent) {
  let rect = document.createElementNS(SVG_NS, 'rect');
  for (let name in o) {
      rect.setAttributeNS(null, name, o[name]);
  }
  parent.appendChild(rect);
  return rect;
}

drawRect(o, bbox);
svg{border:1px solid;}
<svg width="500px" height="300px" preserveAspectRatio="none" viewBox="0,0,5.0,3.0">
  <g id="bbox"></g>
    <g id="test" transform="translate(0 0)">
        <rect x="1" y="0.25" width="0.5" height="0.5" fill="green" />
        <rect x="1.95" y="1" width="0.5" height="0.5" fill="red" />
    </g>
</svg>

I hope it helps

Upvotes: 3

Related Questions