如何在D3中设置<text>元素以填充父容器剩余空间?UNICEF/react-org-chart文本宽度与换行异常问题求助
Hey there! Let's work through this text wrapping issue you're hitting. The core problem here is a common SVG gotcha—<text> elements don't support width attributes or styles like HTML elements do. Your current attempts to set width: 200 aren't having any effect because SVG text doesn't respect those properties. Let's break down how to fix this properly.
Step 1: Remove Invalid Width Settings
First, delete these lines from your text element setup—they're doing nothing for SVG text:
.style('width', 200) .attr('width', 200)
Step 2: Fix Your Custom Wrap Function
Looking at your wrap code, there's a hardcoded test line that's overriding the actual name text, throwing off your width calculation logic. Here's the corrected version:
function wrap(text, width) { text.each(function (d) { var text = d3.select(this), words = d.person.name.split(/\s+/).reverse(), word, line = [], lineNumber = 0, lineHeight = 1.1, // ems y = text.attr('y'), dy = parseFloat(text.attr('dy')), tspan = text .text(null) .append('tspan') .attr('x', 0) .attr('y', y) .attr('dy', dy + 'em'); while ((word = words.pop())) { line.push(word); // Use the actual line content instead of hardcoded text tspan.text(line.join(' ')); if (tspan.node().getComputedTextLength() > width) { line.pop(); tspan.text(line.join(' ')); line = [word]; tspan = text .append('tspan') .attr('x', 0) .attr('y', y) .attr('dy', ++lineNumber * lineHeight + dy + 'em') .text(word); } } }); }
Step 3: Ensure Parent Container Has Enough Space
Even if your wrap logic works, the UNICEF/react-org-chart might be constraining the parent node (like a <rect> or <g> element) to a fixed width. Check if the component accepts props like nodeWidth to adjust the container size—you'll need to set this to at least 200px to match your wrap width.
Step 4: Update Your Text Element Initialization
Here's the cleaned-up code for creating your text element, with the invalid width settings removed:
nodeEnter .append('text') .attr('class', PERSON_NAME_CLASS + ' unedited') .attr('x', namePosition.x) .attr('y', namePosition.y) .attr('dy', '.3em') .style('cursor', 'pointer') .style('fill', nameColor) .style('font-size', 14) .call((text) => { wrap(text, 200) });
Extra Tips
- Font Loading: If
getComputedTextLength()returns incorrect values, make sure your fonts are fully loaded before calling the wrap function. You can usedocument.fonts.readyto wait for font loading in a useEffect hook. - Text Alignment: Adjust the
xattribute of your<text>element if needed to center or align the text within the wider node container. - Position Text Handling: Apply the same wrap logic to your position text element using a matching width to prevent overflow there too.
内容的提问来源于stack exchange,提问作者Demetrius

