(function() { const dom = document.getElementById('chart-tree'); const width = dom.clientWidth || 800; const height = 450; const data = { name: '根节点', children: [ { name: '分支A', children: [{ name: '叶A1', value: 15 }, { name: '叶A2', value: 20 }] }, { name: '分支B', children: [{ name: '叶B1', value: 12 }, { name: '叶B2', value: 18 }, { name: '叶B3', value: 8 }] }, { name: '分支C', children: [{ name: '叶C1', value: 25 }, { name: '叶C2', value: 10 }] } ] }; const svg = d3.select(dom).append('svg').attr('width', width).attr('height', height); const g = svg.append('g').attr('transform', `translate(60,${height / 2})`); const root = d3.hierarchy(data); const treeLayout = d3.tree().size([height - 80, width - 160]); treeLayout(root); // 连线 g.selectAll('.link').data(root.links()).join('path') .attr('d', d3.linkHorizontal().x(d => d.y).y(d => d.x)) .attr('fill', 'none').attr('stroke', '#94a3b8').attr('stroke-width', 1.5); // 节点 const node = g.selectAll('.node').data(root.descendants()).join('g') .attr('transform', d => `translate(${d.y},${d.x})`); node.append('circle').attr('r', 6).attr('fill', d => d.children ? '#3b82f6' : '#22c55e'); node.append('text') .attr('dy', d => d.children ? -12 : 16) .attr('text-anchor', 'middle') .attr('font-size', 11) .text(d => d.data.name + (d.data.value ? ' (' + d.data.value + ')' : '')); window.addEventListener('resize', () => { const w = dom.clientWidth || 800; svg.attr('width', w); }); })();