How to get the position and width of a tspan element
I am working with d3js where lib create nodes and links according to data. At some place have some specific requirement to add multiple text in same line like url "www.xyz.com/home/user" (here 3 strings "www.xyz.com","/home","/user"). They are not separate nodes so I can't find position with d3. It's just a <text> element with 3 <tspan> children.
<text id="TaxFilingResource_URL" class="label url" dy="24" dx="30"> <tspan id="TaxFilingResource.URL.1">www.xyz.com</tspan> <tspan id="TaxFilingResource.URL.2">/home</tspan> <tspan id="TaxFilingResource.URL.3">/user</tspan> </text>
and displaying like this below
I need to get the position and width of each <tspan> element. My code is
var el = document.getElementById(d.source); x = el.getStartPositionOfChar('').x (or) x = el.getClientRects().left;
that give relative position on text inside g element , but in some browser and on mac it will return absolute position.
In SVG 1.1 tspan doesn't have a getBBox method, but in SVG2 it does, I've reported a chromium bug for it reporting the wrong value, http://code.google.com/p/chromium/issues/detail?id=349835.
This would give you the proper position and dimensions if the browsers implemented SVG2:
var bbox = document.getElementById("TaxFilingResource.URL.2").getBBox();
See jsfiddle for a full example.
For now, you can do a workaround using the methods that are available in SVG 1.1:
var home = document.getElementById("TaxFilingResource.URL.2"); var extent = home.getExtentOfChar(0); // pos+dimensions of the first glyph var width = home.getComputedTextLength(); // width of the tspan var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); rect.x.baseVal.value = extent.x; rect.y.baseVal.value = extent.y; rect.width.baseVal.value = width; rect.height.baseVal.value = extent.height;
If you need to transform to another place in the tree:
var dest = document.getElementById("dest"); // some arbitrary container element var fromHometoDestmatrix = home.getTransformToElement(dest); rect.transform.baseVal.appendItem( rect.transform.baseVal.createSVGTransformFromMatrix(fromHometoDestmatrix)); dest.appendChild(rect);