I am trying to find the length of a SVG Text element.
I can select the node and display the node but the .getComputedTextLength() on the node is returning zero.
I have a function that does basically the same thing, but it returns the correct length.
for (let i = 0; i < 23; i++) {
svg.append('text')
.style("font-size", "24px")
.style("font-family", "sans-serif")
.attr('x',10)
.attr('y',32.75*i)
.attr('id', `T${i}`)
.text(reo[i].Māori);
let s = svg.selectAll(`#T${i}`).node()//.getComputedTextLength()
console.log('s',s,s.getComputedTextLength(), textSize(reo[i].Māori)) // y s.getComputedTextLength() no works?
It’s odd (to me) that I can do a selectAll() on the DOM for the Text element’s ID because that implies to me that it is appended to the DOM.
Oh well I will be using the textSize() function to work out the elements width and height. Thanks for the help @Fil
function textSize(text) {
let container = d3.select('body').append('svg');
container.append('text')
.style("font-size", "24px") // todo: these need to be passed to the function or a css style
.style("font-family", "sans-serif")
.text(text);
let sel = container.selectAll('text').node()
let width = sel.getComputedTextLength()
let height = sel.getExtentOfChar(0).height
container.remove()
return {width, height}
}
There’s a difference between d3.selectAll() and container.selectAll(). The former works like document.querySelectorAll(), in which case any elements to be matched have to be attached to the document (the DOM), i.e. be children of it.
The latter queries the children of container. Example:
selects all p elements that are children of the outermost element (the div).
Regarding getComputedTextLength(): As a rule of thumb, whenever a DOM method has computed in its name, it requires the browser to first draw the element in order to figure out the final size/shape/etc. And for that, the element has to be attached to the DOM.
Fun fact: DOM elements have a property isConnected that tells you if the element is attached to the DOM. Here’s a little experiment for you to try, consisting of two cells: