[英]how to create three-level donut chart in d3.js
I'm using trying to create a multi-level donut chart in d3 version5 This image is drawn by d3 version3.我正在尝试在 d3 version5 中创建多级圆环图 此图像由 d3 version3 绘制。 it is working fine in version3.
它在 version3 中工作正常。 I decided to upgrade d3 to the latest version.
我决定将 d3 升级到最新版本。 now, donut chart is not drawn by d3(also no errors in the console)
现在,d3 没有绘制甜甜圈图(控制台中也没有错误)
D3 version 3 > version 5 D3 版本 3 > 版本 5
Here is the sample dataset I used:这是我使用的示例数据集:
Hint: first value in the array is used storage and second is free storage提示:数组中的第一个值是已用存储,第二个是空闲存储
{
average: [30.012, 69.988],
minimum: [10, 90],
maximum: [40, 60]
}
Note: Above data is just a sample this is not exact data.注:以上数据仅为样本,并非准确数据。
Here is the code I tried:这是我试过的代码:
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);
});
Note: This code is working fine in d3 version3 .注意:此代码在d3 version3 中工作正常。
2. Update : 2. 更新:
I've updated the answer with a better solution.我已经用更好的解决方案更新了答案。 I didn't do this at first, because I didn't grasp you structure.
一开始我没有这样做,因为我没有掌握你的结构。 I've updated it to being more D3 idiomatic.
我已将其更新为更符合 D3 惯用语。 Plus it does away with the hack I made in my first update :)
此外,它消除了我在第一次更新中所做的 hack :)
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);
})
})
The updated code uses the index (here j
) that is available when appending the g
elements, which corresponds to you original j
index.更新后的代码使用附加
g
元素时可用的索引(此处为j
),该索引对应于原始j
索引。 This makes it possible to calculate the radii in the original way.这使得以原始方式计算半径成为可能。 To achieve this, the arc appending code is wrapped into a
.each
function that iterates over the g
elements, making j
available to us.为了实现这一点,弧附加代码被包装到一个
.each
函数中,该函数迭代g
元素,使我们可以使用j
。
The class application should work as well, but I've commented it out, as the classFn
function doesn't work, since the classes
variable is not present.类应用程序也应该可以工作,但我已经将其注释掉了,因为
classFn
函数不起作用,因为classes
变量不存在。
1. Update : 1. 更新:
Besides the original answer, when calculating the arc radii you rely on a j
value that is different from D3 v3 and v5.除了原始答案,在计算弧半径时,您依赖于不同于 D3 v3 和 v5 的
j
值。 I summise that j
is used the index of the d3.values
array, so I've cooked up a way to reverse look-up that index based on the input values.我总结出
j
被用作d3.values
数组的索引,所以我想出了一种基于输入值反向查找该索引的方法。
First create a map for reverse mapping data values into their corresponding index:首先创建一个映射,用于将数据值反向映射到它们对应的索引中:
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
}, {})
Then change the last part of your code to:然后将代码的最后一部分更改为:
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);
});
It might not be too pretty, but it's a simple adaption of your code that works.它可能不太漂亮,但它是对您的代码的简单改编。
------- Original answer -------- -------原答案--------
In D3 v5 pie and arc are found at d3.pie
and d3.arc
respectively.在 D3 v5 pie 和 arc 分别位于
d3.pie
和d3.arc
。 Therefore, try changing:因此,尝试更改:
var pie = d3.layout.pie().sort(null);
var arc = d3.svg.arc();
To this instead:对此:
var pie = d3.pie().sort(null);
var arc = d3.arc();
Pie API reference: https://github.com/d3/d3-shape/blob/v1.3.4/README.md#pie饼图 API 参考: https : //github.com/d3/d3-shape/blob/v1.3.4/README.md#pie
Arc API reference: https://github.com/d3/d3-shape/blob/v1.3.4/README.md#arc Arc API 参考: https : //github.com/d3/d3-shape/blob/v1.3.4/README.md#arc
If you use a bundler to bundle sub-modules, both are part of the d3-shape
module.如果您使用捆绑器来捆绑子模块,则它们都是
d3-shape
模块的一部分。 If not they are both available in the full D3 library.如果没有,它们都在完整的 D3 库中可用。
Hope this helps!希望这可以帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.