我正在尝试在D3版本5中创建多级甜甜圈图 此图像由d3版本3绘制。在version3中工作正常。我决定将d3升级到最新版本。现在,d3不会绘制甜甜圈图(控制台中也没有错误)
D3版本3>版本5
这是我使用的示例数据集:
提示::数组中的第一个值是已用存储空间,第二个是免费存储空间< / strong>
{
average: [30.012, 69.988],
minimum: [10, 90],
maximum: [40, 60]
}
注意:以上数据仅是示例,并非精确数据。
这是我尝试的代码:
var width = 300;
var height = 300;
var radius = Math.floor((width / 6) - 2);
var classFn = function(a, b) {
return a === 0 ? classes[b] : 'default';
};
var pie = d3.layout.pie().sort(null);
var arc = d3.svg.arc();
var svg = d3.select(selector).append("svg");
svg.attr("width", width);
svg.attr("height", height);
svg = svg.append("g");
svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var gs = svg.selectAll("g").data(d3.values(dataset)).enter().append("g");
var path = gs.selectAll("path");
path = path.data(function(d) {
return pie(d);
});
path.enter().append("path");
path.attr("class", function(d, i, j) {
return classFn(i, j);
})
path.attr("d", function(d, i, j) {
return arc.innerRadius((j === 0 ? 0 : 2) + radius * j).outerRadius(radius * (j + 1))(d);
});
注意:该代码在 d3版本3 中正常工作。
答案 0 :(得分:0)
2。更新:
我已经用更好的解决方案更新了答案。起初我没有这样做,因为我不了解您的结构。我已将其更新为更加D3惯用的方式。另外,它还消除了我在第一次更新中所做的破解:)
var dataset = {
average: [0, 100],
minimum: [0, 100],
maximum: [0, 100]
}
var width = 300;
var height = 300;
var radius = Math.floor((width / 6) - 2);
var pie = d3.pie().sort(null);
var arc = d3.arc();
var svg = d3.select('body').append("svg");
svg.attr("width", width);
svg.attr("height", height);
svg = svg.append("g");
svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var gs = svg.selectAll("g").data(d3.values(dataset)).enter().append("g");
gs.each(function (d, j) {
d3.select(this).selectAll('path')
.data(pie(d)).enter()
.append('path')
.attr("class", function(d, i) {
// return classFn(i);
})
.attr('d', function (d) {
return arc
.innerRadius((j === 0 ? 0 : 2) + radius * j)
.outerRadius(radius * (j + 1))(d);
})
})
更新的代码使用在附加j
元素时可用的索引(此处为g
),该元素对应于您原始的j
索引。这样就可以以原始方式计算半径。
为此,将弧附加代码包装到.each
元素中的g
函数中,使j
对我们可用。
类应用程序也应该可以正常工作,但由于classFn
函数不存在,因此classes
函数不起作用,因此我已经注释掉了。
1。更新:
除原始答案外,在计算弧半径时,您还依赖于j
值,该值不同于D3 v3和v5。我总结一下,j
被用作d3.values
数组的索引,因此我已经找到了一种基于输入值来反向查找该索引的方法。
首先创建一个映射,用于将数据值反向映射到其对应的索引中:
var dataValueJoinChar = '¤'
var datasetValuesToIndex = d3.values(dataset).reduce((acc, curr, i) => {
acc[`0${dataValueJoinChar}${curr[0]}`] = i
acc[`1${dataValueJoinChar}${curr[1]}`] = i
return acc
}, {})
然后将代码的最后一部分更改为:
path = path.data(function(d) {
return pie(d);
}).enter().append("path");
path.attr("class", function(d, i, j) {
return classFn(i, j);
})
path.attr("d", function(d, i, j) {
var orgIndex = datasetValuesToIndex[`${i}${dataValueJoinChar}${d.data}`]
return arc
.innerRadius((orgIndex === 0 ? 0 : 2) + radius * orgIndex)
.outerRadius(radius * (orgIndex + 1))(d);
});
它可能不太漂亮,但这只是对您的代码进行了简单的改编即可。
------- 原始答案 --------
在D3 v5中,分别在d3.pie
和d3.arc
处找到饼图和圆弧。因此,请尝试更改:
var pie = d3.layout.pie().sort(null);
var arc = d3.svg.arc();
为此:
var pie = d3.pie().sort(null);
var arc = d3.arc();
Pie API参考:https://github.com/d3/d3-shape/blob/v1.3.4/README.md#pie
Arc API参考:https://github.com/d3/d3-shape/blob/v1.3.4/README.md#arc
如果使用捆绑器捆绑子模块,则两者都是d3-shape
模块的一部分。如果没有,则它们都可以在完整的D3库中使用。
希望这会有所帮助!