0

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.

  • is it possible to share the svg tags ? do they have any `id`s or `class`es ? – Towkir Apr 10 '19 at 06:09
  • I have just added an exemple of my js/svg code. – user3102556 Apr 10 '19 at 06:44
  • Can you explain what for do you need the coords? There may be alternative ways. – enxaneta Apr 10 '19 at 06:58
  • I have a function that detects segment intersections, and I want to use it to detect possible intersections between the transformed rects and other svg paths. That's why changing the transformed rects into paths could be a solution... – user3102556 Apr 10 '19 at 07:09
  • Using the `getCTM()` method may help you. Please take a look at the accepted answer for this question: [How get tight bounding box of an SVG Text Element](https://stackoverflow.com/questions/44178791/how-get-tight-bounding-box-of-an-svg-text-element) – enxaneta Apr 10 '19 at 07:41
  • @ enxaneta : thank you so much, this is exactly what I was looking for. – user3102556 Apr 10 '19 at 11:52

1 Answers1

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>
Paul LeBeau
  • 97,474
  • 9
  • 154
  • 181