简体   繁体   中英

Get absolute coordinates of element inside SVG using JS

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.

在此处输入图像描述

  1. Find the cx and cy values of the circle
  2. Apply any transform that the circle has
  3. Step up to each ancestor element and apply any tranforms found
  4. Stop when you reach the root SVG element

 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; 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

I just found, that you can use getBBox() on a SVG element to get its visible rectangle.

var rect = document.getElementById("myrect");
var visibleRect = rect.getBBox();
console.log("x=" + visibleRect.x + ", y=" + visibleRect.y + ", width=" + visibleRect.width + ", height=" + visibleRect.height);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM