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

D3 v4树图文本超出矩形宽度的截断处理问题

解决D3 v4树图文本超出矩形的动态截断问题

问题根源

  1. 判断逻辑失效:你的slice函数里用text.getBoundingClientRect().width做宽度判断,但text是字符串而非DOM元素,完全无法得到正确的宽度对比值。
  2. 固定截断不合理:硬编码slice(0,5)只能固定截断到5字符,无法适配不同宽度的矩形。
  3. 未关联矩形数据:没有利用树图计算好的矩形宽度(d.x1 - d.x0)来确定文本的可用显示空间。

修改方案

1. 重写slice函数

修改函数逻辑,利用绑定的数据获取对应矩形的可用宽度,动态缩短文本直到符合边界:

function slice(d) { 
  var self = d3.select(this), 
      originalText = d.data.name + ' (' + d.data.value +')',
      availableWidth = d.x1 - d.x0 - 12; // 矩形宽度减去左右各6px的预留空白
  let displayText = originalText;

  // 循环截断文本,直到长度符合要求或文本为空
  while (self.node().getComputedTextLength() > availableWidth && displayText.length > 0) {
    displayText = displayText.slice(0, -1); // 每次截断最后一个字符
    self.text(displayText + '...'); // 添加省略号
  }

  // 极端情况处理:避免省略号导致超出
  if (displayText.length !== originalText.length && self.node().getComputedTextLength() > availableWidth) {
    displayText = displayText.slice(0, -3);
    self.text(displayText + '...');
  }
}

2. 删除无效代码

移除这段针对矩形元素的错误文本操作(.label是rect元素,不是文本元素,逻辑完全错误):

d3.selectAll('.label')
  .attr("x", function(t) {
    return Math.max(0, 100-this.textLength.baseVal.value);
  });

3. 保留正确的文本初始化流程

你的原有文本创建逻辑无需改动,确保each(slice)能正确将绑定的数据传入函数:

svg
  .selectAll("text")
  .data(root.leaves())
  .enter()
  .append("text")
    .attr("x", function(d){ return d.x0+6})    
    .attr("y", function(d){ return d.y0+15})    
    .attr('dy', 0)
    .text(function(d){ return d.data.name + ' (' + d.data.value +')' })
    .attr("font-size", "15px")
    .attr("fill", "black")
    .each(slice);

关键说明

  • 可用宽度计算:d.x1 - d.x0是树图算法计算出的矩形实际宽度,减去12px是为了给文本左右预留空白,避免紧贴边框。
  • 动态适配:通过循环逐步缩短文本,确保每个矩形内的文本都能适配自身宽度,不会出现固定截断的生硬效果。
  • 原始文本保留:提前保存完整文本,后续如需扩展(比如tooltip显示完整内容)可直接复用。

内容的提问来源于stack exchange,提问作者rootseire

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 12:55:35