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

D3树状图部分链接线条过粗问题求助

D3.js树状图部分链接过粗问题排查

我用D3.js绘制树状图时,发现部分链接路径比其他链接粗很多,想把这些过粗的路径调整成和垂直路径一致的粗细。查了很多树状图示例,链接线条都是统一粗细,麻烦帮忙排查原因。


Tree 代码

const stratifier = stratify<Leaf>()
  .id((d) => d.name)
  .parentId((d) => d.parentName)

const root = useMemo(() => {
  if (loading) return null
  if (error) return null
  if (data?.leaves.length === 0 || data === undefined) return null

  const leaves =
    data?.leaves.map((leaf) => ({
      name: leaf.name,
      description: leaf.description,
      parentName: leaf.parentName ?? '',
      children:
        leaf.children?.map((leaf) => ({
          name: leaf?.name ?? '',
        })) ?? [],
    })) ?? []

  return stratifier(leaves)
}, [data, stratifier, loading, error])

const setupTree = useMemo(() => {
  if (!root) return
  const result = tree<Leaf>().size([500, 500])(root)
  return result
}, [root])

const links = useMemo(() => setupTree?.links(), [setupTree])
const convertLink = useCallback(
  (link: HierarchyPointLink<Leaf>): DefaultLinkObject => ({
    source: [link.source.x, link.source.y],
    target: [link.target.x, link.target.y],
  }),
[])

JSX 路径代码

{links?.map((link, i) => {
  const convertedLink = convertLink(link)
  return (
    <path
      key={`${i}-link`}
      d={linkVertical()
        .source((d) => d.target)
        .target((d) => d.source)(convertedLink) ?? ''
      }
      stroke="black"
      strokeWidth="2"
      style={{ transform: `translate(${margin}px, ${margin}px)` }}
    />
  )
})}

分层数据

{
    "data": {
        "leaves": [
            {
                "name": "A",
                "parentName": null,
                "description": "This is a description of A",
                "children": [
                    {
                        "name": "B",
                        "__typename": "Leaf"
                    },
                    {
                        "name": "C",
                        "__typename": "Leaf"
                    },
                    {
                        "name": "D",
                        "__typename": "Leaf"
                    }
                ],
                "__typename": "Leaf"
            },
            {
                "name": "B",
                "parentName": "A",
                "description": "This is a description of B",
                "children": [
                    {
                        "name": "B-1",
                        "__typename": "Leaf"
                    },
                    {
                        "name": "B-2",
                        "__typename": "Leaf"
                    },
                    {
                        "name": "B-3",
                        "__typename": "Leaf"
                    }
                ],
                "__typename": "Leaf"
            },
            {
                "name": "B-1",
                "parentName": "B",
                "description": "This is a description of B-1",
                "children": [],
                "__typename": "Leaf"
            },
            {
                "name": "B-2",
                "parentName": "B",
                "description": "This is a description of B-2",
                "children": [],
                "__typename": "Leaf"
            },
            {
                "name": "B-3",
                "parentName": "B",
                "description": "This is a description of B-3",
                "children": [],
                "__typename": "Leaf"
            },
            {
                "name": "C",
                "parentName": "A",
                "description": "This is a description of C",
                "children": [],
                "__typename": "Leaf"
            },
            {
                "name": "D",
                "parentName": "A",
                "description": "This is a description of D",
                "children": [],
                "__typename": "Leaf"
            }
        ]
    }
}

问题根源与修复方案

核心问题

  1. 重复链接生成:你的分层数据中,父节点(如A)既作为独立条目存在,又在自身children数组中列出子节点。stratifier处理时会基于parentId和children数组重复生成同一条链接,两条完全重叠的路径叠加后,视觉上就会显得更粗。
  2. 路径起点终点反转:调用linkVertical()时,错误设置了.source((d) => d.target)和.target((d) => d.source),配合convertLink的正常映射,进一步加剧了路径重叠的问题。

修复步骤

1. 清理数据结构

stratifier只需要每个节点的name(id)和parentName就能构建树,不需要父节点中的children数组,删除该字段避免重复链接:

{
    "data": {
        "leaves": [
            {
                "name": "A",
                "parentName": null,
                "description": "This is a description of A",
                "__typename": "Leaf"
            },
            {
                "name": "B",
                "parentName": "A",
                "description": "This is a description of B",
                "__typename": "Leaf"
            },
            {
                "name": "B-1",
                "parentName": "B",
                "description": "This is a description of B-1",
                "__typename": "Leaf"
            },
            {
                "name": "B-2",
                "parentName": "B",
                "description": "This is a description of B-2",
                "__typename": "Leaf"
            },
            {
                "name": "B-3",
                "parentName": "B",
                "description": "This is a description of B-3",
                "__typename": "Leaf"
            },
            {
                "name": "C",
                "parentName": "A",
                "description": "This is a description of C",
                "__typename": "Leaf"
            },
            {
                "name": "D",
                "parentName": "A",
                "description": "This is a description of D",
                "__typename": "Leaf"
            }
        ]
    }
}

2. 修正链接生成逻辑

去掉linkVertical()的反转设置,直接使用原始链接对象(无需额外转换):

{links?.map((link, i) => (
  <path
    key={`${i}-link`}
    d={linkVertical()(link) ?? ''}
    stroke="black"
    strokeWidth="2"
    style={{ transform: `translate(${margin}px, ${margin}px)` }}
  />
))}

如果确实需要保留转换逻辑,保持convertLink的正确性,不要反转source和target:

const convertLink = useCallback(
  (link: HierarchyPointLink<Leaf>): DefaultLinkObject => ({
    source: [link.source.x, link.source.y],
    target: [link.target.x, link.target.y],
  }),
  []
)
d={linkVertical()(convertedLink) ?? ''}

完成修改后,每个节点间只会生成一条链接,所有线条粗细将保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 23:25:55