Skip to content Skip to sidebar Skip to footer

Svg: Why Does Getboundingclientrect Return 190 When Y Attribute Is 200?

This code below places textBox1 at a y-position of 200, but getBoundingClientRect returns a value of 190. Why? https://codepen.io/anon/pen/REKayR?editors=1011

Solution 1:

.getBoundingClientRect() is part of the generic Element interface, and computes the rectangle in relation to the screen viewport. SVG offer some more specific methods:

  • SVGGraphicsElement.getBBox() computes the bounding box in the local coordinate system the element is drawn in.
  • SVGGraphicsElement.getCTM() computes the transformation matrix getween the local coordinate system and the nearest SVG viewport (a <svg> element, for example).
  • SVGGraphicsElement.getScreenCTM() computes the transformation matrix getween the local coordinate system and the screen viewport.

In addition, the DOMMatrix interface has an .inverse() method, so you can easily compute positions in the opposite direction. (For example, if you transform a mouse event screenx/screenY position with the result of element.getScreenCTM().inverse(), you'll get the mouse position in relation to that element.)

The one thing a bit awkward is that you have to construct a SVGPoint object, which can only be achieved by the SVGSVGElement.createSVGPoint() method on an <svg> element, to have something to apply your matrix to.

As for your question, consider the different return values for the three doordinate systems for the rect inside the inner <svg>:

var textBox = document.querySelector('#textBox1 rect');
var svg = document.querySelector('#rootBox');
var point = svg.createSVGPoint();

var local = textBox.getBBox();
point.x = local.x, point.y = local.y;
console.log("local: ", local.x, local.y);

var nearest = textBox.getCTM();
var point2 = point.matrixTransform(nearest);
console.log("nearest viewport: ", point2.x, point2.y);

var screen = textBox.getScreenCTM();
var point3 = point.matrixTransform(screen);
console.log("screen viewport: ", point3.x, point3.y);
<svgid="rootBox"width="500"height="800"xmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink"><rectx="0%"y="0%"width="100%"height="100%"fill="beige" /><svgid="textBox1"x="0%"y="200"width="100%"height="25%"><rectclass="background"x="0%"y="0%"width="100%"height="100%"fill="gray"fill-opacity="0.5" /><textclass="textGroup"x="0"y="0"><tspanx="50%"dy="-0.25em"text-anchor="middle">tspan line 0</tspan><tspanx="50%"dy="1.5em"text-anchor="middle">tspan line 1</tspan><tspanx="50%"dy="1.5em"text-anchor="middle">tspan line 2</tspan></text></svg></svg>

Solution 2:

getBoundingClientRect takes things like scroll position into account. Any margin or padding on the HTML body would also factor in, but adding to the result rather than subtracting.

If you make sure you aren't scrolled down, and the margins do not factor in, you will get 200:

functionlog() {
  var textBox = $("#textBox1");
  var textBBox = textBox[0].getBoundingClientRect();
  console.log("The y-pos is: " + textBBox.y);
}
log();
setInterval(log, 1000);
html,
body {
  margin: 0;
  padding: 0;
}
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><svgid="rootBox"width="500"height="800"xmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink"><rectx="0%"y="0%"width="100%"height="100%"fill="beige" /><svgid="textBox1"x="0%"y="200"width="100%"height="25%"><rectclass="background"x="0%"y="0%"width="100%"height="100%"fill="gray"fill-opacity="0.5" /><textclass="textGroup"x="0"y="0"><tspanx="50%"dy="-0.25em"text-anchor="middle">tspan line 0</tspan><tspanx="50%"dy="1.5em"text-anchor="middle">tspan line 1</tspan><tspanx="50%"dy="1.5em"text-anchor="middle">tspan line 2</tspan></text></svg></svg>

Post a Comment for "Svg: Why Does Getboundingclientrect Return 190 When Y Attribute Is 200?"