Good time forum users. I apologize in advance for my English. I could not find the answer (I decided to ask the English-speaking audience).
Absolute positioning (coordinates) of an element nested in groups relative to the parent container ().
<svg width="100%" height="100%" viewBox="0 0 1000 1000" preserveAspectRatio="xMidYMin slice" x="0" y="0" tabindex="1">
<g transform="translate(100 100)">
<g transform="translate(100 100)">
<circle r="50" cx="25" cy="25" fill="yellow" />
</g>
</g>
<svg>
I would like to get using ES6 + circle coordinates relative to SVG. That is x = 100 + 100 + 25, y = 100 + 100 + 25 for .
How can I get these coordinates? (can be up to an infinite nesting of groups). Thanks for helping.
cx
and cy
values of the circlefunction getCirclePosition(circleElemId)
{
var elem = document.getElementById(circleElemId);
var svg = elem.ownerSVGElement;
// Get the cx and cy coordinates
var pt = svg.createSVGPoint();
pt.x = elem.cx.baseVal.value;
pt.y = elem.cy.baseVal.value;
while (true)
{
// Get this elements transform
var transform = elem.transform.baseVal.consolidate();
// If it has a transform, then apply it to our point
if (transform) {
var matrix = elem.transform.baseVal.consolidate().matrix;
pt = pt.matrixTransform(matrix);
}
// If this element's parent is the root SVG element, then stop
if (elem.parentNode == svg)
break;
// Otherwise step up to the parent element and repeat the process
elem = elem.parentNode;
}
return pt;
}
var pos = getCirclePosition("thecircle");
console.log("Coordinates are: " + pos.x + "," + pos.y);
<svg width="100%" height="100%" viewBox="0 0 1000 1000" preserveAspectRatio="xMidYMin slice" x="0" y="0" tabindex="1">
<g transform="translate(100 100)">
<g transform="translate(100 100)">
<circle id="thecircle" r="50" cx="25" cy="25" fill="yellow" />
</g>
</g>
<svg>
Update
As @Vad0k pointed out, there is a simpler, but slighlty less accurate approach, that can be used instead:
function getCirclePosition(circleElemId)
{
var elem = document.getElementById(circleElemId);
var svg = elem.ownerSVGElement;
// Get the cx and cy coordinates
var pt = svg.createSVGPoint();
pt.x = elem.cx.baseVal.value;
pt.y = elem.cy.baseVal.value;
return pt.matrixTransform(getTransformToElement(elem, svg));
}
function getTransformToElement(fromElement, toElement) {
return toElement.getCTM().inverse().multiply(fromElement.getCTM());
};
var pos = getCirclePosition("thecircle");
console.log("Coordinates are: " + pos.x + "," + pos.y);
<svg width="100%" height="100%" viewBox="0 0 1000 1000" preserveAspectRatio="xMidYMin slice" x="0" y="0" tabindex="1">
<g transform="translate(100 100)">
<g transform="translate(100 100)">
<circle id="thecircle" r="50" cx="25" cy="25" fill="yellow" />
</g>
</g>
<svg>
Obtain the childs and parents top and left and get the difference
const circleLeft = circleElement.getBoundingRect().offsetLeft
const circleTop = circleElement.getBoundingRect().top
const parentLeft = circleElement.parentElement.getBoundingRect().offsetLeft
const parentTop = circleElement.parentElement.getBoundingRect().top
const changeInX = parentLeft - cirleLeft
const changeInY = parentTop - circleTop
If you are registering events on this elements, Register them as capturing event rather than bubbling event by passing true
as third argument to addEventListener
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With