You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在D3中设置<text>元素以填充父容器剩余空间?UNICEF/react-org-chart文本宽度与换行异常问题求助

Fixing SVG Text Width & Tspan Wrapping in D3 + 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 use document.fonts.ready to wait for font loading in a useEffect hook.
  • Text Alignment: Adjust the x attribute 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 22:42:30