D3.js绘制双层环形图时Level2起始扇区不显示的技术问题
解决D3.js嵌套环形饼图Level2扇区缺失问题
我之前碰到过一模一样的情况,问题根源出在你两次绘制环形图时共用了同一个类名,导致D3的数据绑定逻辑发生冲突。
问题分析
当你绘制Level1环形图时,通过g.selectAll(".arc").data(pie(data)).enter()创建了一批带.arc类的<g>元素。等到绘制Level2时,再次调用g.selectAll(".arc")会直接选中这些已存在的元素。如果Level2的数据条目数和Level1相同或更少,enter()方法只会创建超出已有元素数量的新元素,而前面的元素会进入update阶段,但你的代码完全没处理这部分逻辑,直接跳过了,这就导致Level2开头的扇区根本没被创建出来。
解决方案
给两个环形图的组元素设置不同的类名,让D3能分别选择和绑定数据,互不干扰。修改后的代码如下:
Level1环形图绘制代码(修改类名为.arc-level1)
d3.json("http://localhost:50025/SportsWheelServices.asmx/WheelLevel1", function (error, data) { data.forEach(function (d) { d.SectionId = d.SectionId; d.SectionLevel1 = d.SectionLevel1; d.GroupName = d.GroupName; d.SectionUpColor = d.SectionUpColor; d.Rotation = d.Rotation; }); var label = d3.arc() .outerRadius(radius - 20) .innerRadius(400); var pie = d3.pie() .sort(null) .value(function (d) { return d.SectionLevel1; }); var arc = d3.arc() .outerRadius(radius - 20) .innerRadius(400); var arcs = g.selectAll(".arc-level1") // 修改类名,避免和Level2冲突 .data(pie(data)) .enter().append("g") .attr("class", "arc-level1"); // 设置专属类名 arcs.append("path") .attr("d", arc) .attr("fill", function (d, i) { return colors(data[i].SectionUpColor); }); arcs.append("text") .attr("transform", function (d) { var rotation = d.endAngle < Math.PI ? (d.startAngle / 2 + d.endAngle / 2) * 180 / Math.PI : (d.startAngle / 2 + d.endAngle / 2 + Math.PI) * 180 / Math.PI; return "translate(" + label.centroid(d) + ") rotate("+ d.data.Rotation+") rotate(" + rotation + ")"; }) .attr("dy", "0.35em") .text(function (d) { return d.data.GroupName; }); });
Level2环形图绘制代码(修改类名为.arc-level2)
d3.json("http://localhost:50025/SportsWheelServices.asmx/WheelLevel2", function (error, data) { data.forEach(function(d) { d.SectionId = d.SectionId; d.SectionLevel2 = d.SectionLevel2; }); var label = d3.arc() .outerRadius(radius - 20) .innerRadius(300); var pie = d3.pie() .sort(null) .value(function (d) { return d.SectionLevel2; }); var arc = d3.arc() .outerRadius(radius - 20) .innerRadius(300); var arcs = g.selectAll(".arc-level2") // 修改类名,避免和Level1冲突 .data(pie(data)) .enter().append("g") .attr("class", "arc-level2"); // 设置专属类名 arcs.append("path") .attr("d", arc) .attr("fill", function (d, i) { return colors(i); }); });
额外优化建议
你可以检查下两个环形的半径设置:Level1的innerRadius是400,而Level2的outerRadius是radius-20,如果radius-20大于400,两个环形会重叠,可能造成视觉上的遮挡。建议把Level2的outerRadius调整为390左右,确保和Level1的环形有间隔,显示更清晰。
内容的提问来源于stack exchange,提问作者Sham Yemul
相关产品推荐
相关产品推荐

