'svg : find x,y coordinates of rect vertices

I have various svg rects on a web page on which a transform is applied in the form :

    transform="translate(418 258) rotate(-45.2033 15 18) scale(2.5 2.5)"

I need to get the x,y coordinates of the 4 vertices of each rect after the transform is applied.

Here is an exemple of code :

<g transform="translate(418 258) rotate(-45.25 15 18) scale(2.5 2.5)">
  <rect id="box" x="0" y="0" width="31" height="37" style="fill:none;stroke:rgb(102, 102, 102);stroke-width:1.5px;">
  </rect>
</g>

I have tried the following formula in plain js :

x' = x * cos(angle) + y * sin(angle)
y' = -x * sin(angle) + y * cos(angle)

but the results are slightly different from the svg display in various browsers.

I guess this can be done using js/svg primitives, but I don't know how, and didn't find any code example. Perhaps changing the rects into paths after transform would do the trick...

Last but not least, I'm using jquery but not d3.

Thanks in advance.



Solution 1:[1]

You can read the transform attribute and convert it to a matrix. Then for each of the rectangle's four corners, you can use that matrix to calculate the transformed corner locations.

See the following demo.

This demo assumes that there is an element with id of "box", and that the transform you care about is just the one on the parent <g> element. If your circumstances are more complex than that, then you will need to do some more work on this code.

// Get a reference to the "box" rect element
var box = document.getElementById("box");
// Get its x, y, width and height
var bx = box.x.baseVal.value;
var by = box.y.baseVal.value;
var bw = box.width.baseVal.value;
var bh = box.height.baseVal.value;

// Get the box's parent element (the <g>)
var parentGroup = box.parentNode;
// Read the transform attribute and convert it to a transform matrix object
var transformMatrix = parentGroup.transform.baseVal.consolidate().matrix;

// For each of the rectangle's four corners, use the transform matrix to calculate its new coordinates
console.log("point 1 = ", doPoint(bx, by));
console.log("point 2 = ", doPoint(bx + bw, by));
console.log("point 3 = ", doPoint(bx + bw, by + bh));
console.log("point 4 = ", doPoint(bx, by + bh));



function doPoint(x, y)
{
  // We need a reference to the <svg> element for the next step
  var svg = box.ownerSVGElement;
  // Create an SVGPoint object with the correct x and y values
  var pt = svg.createSVGPoint();
  pt.x = x;
  pt.y = y;
  // Use the "matrixTransform()" method on SVGPoint to apply the transform matrix to the coordinate values
  pt = pt.matrixTransform(transformMatrix);
  // Return the updated x and y values
  return {x: pt.x, y: pt.y};
}
<svg>
  <g transform="translate(418 258) rotate(-45.25 15 18) scale(2.5 2.5)">
    <rect id="box" x="0" y="0" width="31" height="37" style="fill:none;stroke:rgb(102, 102, 102);stroke-width:1.5px;">
    </rect>
  </g>
</svg>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Paul LeBeau