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

如何在D3 v7.6.1+TypeScript的饼图中实现文本换行及this引用

问题解决方案

一、箭头函数中替代d3.select(this)的写法

D3 v7的.each()方法回调函数提供三个参数:(数据d, 索引i, 节点数组nodes),箭头函数里可通过nodes[i]获取当前遍历的元素,再用d3.select()包裹,替代原有的d3.select(this)。

示例:

d3.selectAll('text').each((d, i, nodes) => {
  const currentText = d3.select(nodes[i]);
  // 基于currentText执行后续操作
});

二、适配TypeScript和D3 v7.6.1的wrap函数

原函数需补充类型注解,同时调整箭头函数的元素引用逻辑,以下是修改后的完整版本:

import * as d3 from 'd3';

// 定义wrap函数类型:接收文本元素选择器和换行宽度
function wrap(
  text: d3.Selection<SVGTextElement, unknown, HTMLElement, any>,
  width: number
) {
  text.each((_, i, nodes) => {
    // 获取当前文本元素
    const currentText = d3.select(nodes[i]);
    // 拆分文本为单词数组并反转
    const words = currentText.text().split(/\s+/).reverse();
    let word: string | undefined;
    const line: string[] = [];
    let lineNumber = 0;
    const lineHeight = 1.1; // 行高(em单位)
    const y = currentText.attr('y') || '0';
    const dy = parseFloat(currentText.attr('dy') || '0');
    
    // 清空原文本,添加第一个tspan容器
    let tspan = currentText.text(null)
      .append('tspan')
      .attr('x', 0)
      .attr('y', y)
      .attr('dy', `${dy}em`);
    
    while (word = words.pop()) {
      line.push(word);
      tspan.text(line.join(' '));
      // 检查当前行宽度是否超出限制
      const tspanNode = tspan.node();
      if (tspanNode && tspanNode.getComputedTextLength() > width) {
        line.pop();
        tspan.text(line.join(' '));
        line = [word];
        // 添加新tspan,设置行偏移量
        tspan = currentText.append('tspan')
          .attr('x', 0)
          .attr('y', y)
          .attr('dy', `${++lineNumber * lineHeight + dy}em`)
          .text(word);
      }
    }
  });
}

// React组件中的使用示例(结合useEffect)
function PieChart() {
  React.useEffect(() => {
    // 给svg添加文本并调用换行函数
    d3.select('svg')
      .append('text')
      .text('This is a circle with some text in it.')
      .attr('x', 20)
      .attr('y', 20)
      .call(wrap, 100);
  }, []);

  return <svg width={400} height={400}></svg>;
}

关键调整说明:

  1. 类型注解:给函数参数补充TypeScript类型,明确text是D3文本元素选择器类型,避免类型报错。
  2. 元素引用:在.each()的箭头函数中,通过nodes[i]获取当前元素,替代原有的this绑定。
  3. 空值处理:对attr('y')和attr('dy')的返回值设置默认值,避免parseFloat处理空值报错。
  4. 节点校验:调用getComputedTextLength()前先检查tspan.node()是否存在,符合TypeScript严格类型要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 01:25:24