Building a D3 property that renders text. My loop prints to console.log()
just fine and the loop before works ok too. Below we are looking at the label array[]
that I will loop through, loop through links
then through label
e.g.
Data:
links: [
{
id: 1,
source: 1,
target: 2,
type: 'Foo',
label: ['Jim', 'Phil'],
since: 2010,
}
]
D3 snippet:
const edgelabels = zoomContainer
.selectAll('.edgelabel')
.data(links)
.enter()
.append('text')
.style('pointer-events', 'none')
.attr('class', 'edgelabel')
.attr('id', function (d, i) {
return 'edgelabel' i;
})
.attr('font-size', 10)
.attr('fill', '#aaa');
edgelabels
.append('textPath')
.attr('xlink:href', function (d, i) {
return '#edgepath' i;
})
.style('text-anchor', 'middle')
.style('pointer-events', 'none')
.attr('startOffset', '50%')
.append('tspan')
.text((d) => d.label)
// .text((d) => d.label.forEach((x) => x))
.attr('x', -10)
.attr('dx', 10)
.attr('dy', 22);
The above renders this:
<text id="edgelabel0" font-size="10" fill="#aaa" style="pointer-events: none;" transform="rotate(0)">
<textPath xlink:href="#edgepath0" startOffset="50%" style="text-anchor: middle; pointer-events: none;">
<tspan x="-10" dx="10" dy="22">
Jim,Phil
</tspan>
</textPath>
</text>
But what I want is this:
<text id="edgelabel0" font-size="10" fill="#aaa" style="pointer-events: none;" transform="rotate(0)">
<textPath xlink:href="#edgepath0" startOffset="50%" style="text-anchor: middle; pointer-events: none;">
<tspan x="-10" dx="10" dy="22">
Jim
</tspan>
<tspan x="-10" dx="10" dy="22">
Phil
</tspan>
</textPath>
</text>
So the label array items are in their own <tspan>
.
Ive replaced .text((d) => d.label)
with .text((d) => d.label.forEach((x) => { return x;}))
and that seems to console.log()
correctly, separating "Jim" and "Phil". However, the <tspan>
remains empty and not adding another <tspan>
for additional items in the array.
I've looked into using .each
for the approach as that would be preferable to d3 so it seems and maybe that was part of the issue? Any help from somebody with more d3 experience would be appreciated. thanks
Here is a demo (lines 196/197)
CodePudding user response:
No need to use any looping techniques... hope this helps somebody else.
const edgelabels = zoomContainer
.selectAll('.edgelabel')
.data(links)
.enter()
.append('text')
.style('pointer-events', 'none')
.attr('class', 'edgelabel')
.attr('id', function (d, i) {
return 'edgelabel' i;
})
.attr('font-size', 10)
.attr('fill', '#aaa');
edgelabels
.append('textPath')
.attr('xlink:href', function (d, i) {
return '#edgepath' i;
})
.style('text-anchor', 'middle')
.style('pointer-events', 'none')
.attr('startOffset', '50%')
.selectAll('tspan.textPath')
.data((d, i) => d.label)
.enter()
.append('tspan')
.attr('class', 'text')
.text((d) => d)
.attr('x', -10)
.attr('dx', 10)
.attr('dy', 22);