英文:
Equivalent of chord.groups in D3.js v7
问题
我正在尝试重新创建Nadia Bremer的故事数据和弦图,来自https://gist.github.com/nbremer/94db779237655907b907
在创建g元素时,她访问chord.groups元素:
var g = svg.selectAll("g.group")
.data(chord.groups)
.enter().append("svg:g")
.attr("class", function(d) {return "group " + NameProvider[d.index];});
这在D3版本3中运行正常。这里有一个有效的jsfiddle。
然而,在D3版本7中,当我尝试相同的操作时,chord.groups变为未定义。这里是一个包含v7变体的jsfiddle,在访问chord.groups时会出错。
d3.chord()参考说明:“和弦数组还定义了一个长度为n的辅助数组chords.groups,其中每个组表示节点i的综合流出量...”
我还发现在Observable上有几个示例访问chord.groups,它们都正常运行。我做错了什么?
1: https://gist.github.com/nbremer/94db779237655907b907
2: http://jsfiddle.net/j4a1byk5/
3: http://jsfiddle.net/4bL28zpn/
4: https://github.com/d3/d3-chord
英文:
I am trying to recreate Nadia Bremer's chord diagram for storytelling with data from https://gist.github.com/nbremer/94db779237655907b907
She accesses the chord.groups element when creating the g element:
var g = svg.selectAll("g.group")
.data(chord.groups)
.enter().append("svg:g")
.attr("class", function(d) {return "group " + NameProvider[d.index];});
This works fine in v3 of D3. Here's a jsfiddle that works
However, when I try the same thing in D3 v7, chord.groups becomes undefined. Here is a jsfiddle with the v7 variant which gives an error when accessing chord.groups
The d3.chord() reference states that "The chords array also defines a secondary array of length n, chords.groups, where each group represents the combined outflow for node i..."
I've also found several examples on Observable which access chord.groups and they run fine. What am I doing wrong?
答案1
得分: 3
以下是您要翻译的内容:
"The error is very subtle, and here I'd blame the docs for lack of clarity, not you."
"问题非常微妙,我认为这里应该怪文档不够清晰,而不是你。"
"The problem is that you passed the data to the chord generator like this:"
"问题在于你把数据传递给和弦生成器的方式如下:"
"var chord = d3.chord(matrix)"
"但是 d3.chord()
不接受参数。相反,它返回一个接受参数的函数。因此,应该是:"
"但是 d3.chord()
不接受参数。相反,它返回一个接受参数的函数。因此,应该是:"
"var chord = d3.chord()(matrix)"
"Alternatively, defining the generator and then passing the data:"
"或者,定义生成器然后传递数据:"
"const chord = d3.chord();"
"const chordLayout = chord(matrix);"
"As you can see, it's a bit different. The confusion is maybe worsened by the fact that some D3 methods, like scales, accept data arguments like that, e. g. d3.scaleLinear(domain, range)
."
"正如你所看到的,有些 D3 方法(比如比例尺)接受这样的数据参数,这可能会加深混淆,例如 d3.scaleLinear(domain, range)
。"
"Most of D3 generators are like this. For instance, using a common line generator..."
"大多数 D3 生成器都是这样的。例如,使用一个普通的线生成器..."
"const lineGenerator = d3.line();"
"You get the path d
attribute using:"
"你可以使用以下方式获取路径 d
属性:"
"lineGenerator(data);"
"Which is the same of d3.line()(data)
, but it's not the same of d3.line(data)
."
"这与 d3.line()(data)
是相同的,但与 d3.line(data)
不同。"
"Here's your working v7 version:"
"以下是您的可运行的 v7 版本:"
""
""
"var NameProvider = ["Apple", "HTC", "Huawei", "LG", "Nokia", "Samsung", "Sony", "Other"];"
"var matrix = ["
" [9.6899, 0.8859, 0.0554, 0.443, 2.5471, 2.4363, 0.5537, 2.5471], /Apple 19.1584/"
" [0.1107, 1.8272, 0, 0.4983, 1.1074, 1.052, 0.2215, 0.4983], /HTC 5.3154/"
" [0.0554, 0.2769, 0.2215, 0.2215, 0.3876, 0.8306, 0.0554, 0.3322], /Huawei 2.3811/"
" [0.0554, 0.1107, 0.0554, 1.2182, 1.1628, 0.6645, 0.4983, 1.052], /LG 4.8173/"
" [0.2215, 0.443, 0, 0.2769, 10.4097, 1.2182, 0.4983, 2.8239], /Nokia 15.8915/"
" [1.1628, 2.6024, 0, 1.3843, 8.7486, 16.8328, 1.7165, 5.5925], /Samsung 38.0399/"
" [0.0554, 0.4983, 0, 0.3322, 0.443, 0.8859, 1.7719, 0.443], /Sony 4.4297/"
" [0.2215, 0.7198, 0, 0.3322, 1.6611, 1.495, 0.1107, 5.4264] /Other 9.9667/"
"];"
"/Sums up to exactly 100/"
"var colors = ["#C4C4C4", "#69B40F", "#EC1D25", "#C8125C", "#008FC8", "#10218B", "#134B24", "#737373"];"
"/Initiate the color scale/"
"var fill = d3.scaleOrdinal()"
" .domain(d3.range(NameProvider.length))"
" .range(colors);"
"///////////////////////////////////////////////////////////"
"/////////////////// Initiate Chord Diagram /////////////////////"
"/////////////////////////////////////////////////////////"
"var margin = {"
" top: 30,"
" right: 25,"
" bottom: 20,"
" left: 25"
" },"
" width = 650 - margin.left - margin.right,"
" height = 600 - margin.top - margin.bottom,"
" innerRadius = Math.min(width, height) * .39,"
" outerRadius = innerRadius * 1.04;"
"/Initiate the SVG/"
"var svg = d3.select("#chart")"
" .attr("width", width + margin.left + margin.right)"
" .attr("height", height + margin.top + margin.bottom)"
" .append("svg:g")"
" .attr("transform", "translate(" + (margin.left + width / 2) + "," + (margin.top + height / 2) + ")");"
"var chord = d3.chord()"
" .sortSubgroups(d3.descending) /sort the chords inside an arc from high to low/"
" .sortChords(d3.descending)(matrix);"
"///////////////////////////////////////////////////////////"
"//////////////// Draw outer Arcs /////////////////////////"
"/////////////////////////////////////////////////////////"
"var arc = d3.arc()"
" .innerRadius(innerRadius)"
" .outerRadius(outerRadius);"
"var g = svg.selectAll("g.group")"
" .data(chord.groups)"
" .enter().append("svg:g")"
" .attr("class", function(d) {"
" return "group " + NameProvider[d.index];"
" });"
"g.append("svg:path")"
" .attr("class", "arc")"
" .
英文:
The error is very subtle, and here I'd blame the docs for lack of clarity, not you.
The problem is that you passed the data to the chord generator like this:
var chord = d3.chord(matrix)
But d3.chord()
doesn't accept arguments. Instead, it returns a function which accepts the arguments. Thus, it should be:
var chord = d3.chord()(matrix)
Alternatively, defining the generator and then passing the data:
const chord = d3.chord();
const chordLayout = chord(matrix);
As you can see, it's a bit different. The confusion is maybe worsened by the fact that some D3 methods, like scales, accept data arguments like that, e. g. d3.scaleLinear(domain, range)
.
Most of D3 generators are like this. For instance, using a common line generator...
const lineGenerator = d3.line();
You get the path d
attribute using:
lineGenerator(data);
Which is the same of d3.line()(data)
, but it's not the same of d3.line(data)
.
Here's your working v7 version:
<!-- begin snippet: js hide: true console: true babel: false -->
<!-- language: lang-js -->
var NameProvider = ["Apple", "HTC", "Huawei", "LG", "Nokia", "Samsung", "Sony", "Other"];
var matrix = [
[9.6899, 0.8859, 0.0554, 0.443, 2.5471, 2.4363, 0.5537, 2.5471], /*Apple 19.1584*/
[0.1107, 1.8272, 0, 0.4983, 1.1074, 1.052, 0.2215, 0.4983], /*HTC 5.3154*/
[0.0554, 0.2769, 0.2215, 0.2215, 0.3876, 0.8306, 0.0554, 0.3322], /*Huawei 2.3811*/
[0.0554, 0.1107, 0.0554, 1.2182, 1.1628, 0.6645, 0.4983, 1.052], /*LG 4.8173*/
[0.2215, 0.443, 0, 0.2769, 10.4097, 1.2182, 0.4983, 2.8239], /*Nokia 15.8915*/
[1.1628, 2.6024, 0, 1.3843, 8.7486, 16.8328, 1.7165, 5.5925], /*Samsung 38.0399*/
[0.0554, 0.4983, 0, 0.3322, 0.443, 0.8859, 1.7719, 0.443], /*Sony 4.4297*/
[0.2215, 0.7198, 0, 0.3322, 1.6611, 1.495, 0.1107, 5.4264] /*Other 9.9667*/
];
/*Sums up to exactly 100*/
var colors = ["#C4C4C4", "#69B40F", "#EC1D25", "#C8125C", "#008FC8", "#10218B", "#134B24", "#737373"];
/*Initiate the color scale*/
var fill = d3.scaleOrdinal()
.domain(d3.range(NameProvider.length))
.range(colors);
/*//////////////////////////////////////////////////////////
/////////////// Initiate Chord Diagram /////////////////////
//////////////////////////////////////////////////////////*/
var margin = {
top: 30,
right: 25,
bottom: 20,
left: 25
},
width = 650 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom,
innerRadius = Math.min(width, height) * .39,
outerRadius = innerRadius * 1.04;
/*Initiate the SVG*/
var svg = d3.select("#chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("svg:g")
.attr("transform", "translate(" + (margin.left + width / 2) + "," + (margin.top + height / 2) + ")");
var chord = d3.chord()
.sortSubgroups(d3.descending) /*sort the chords inside an arc from high to low*/
.sortChords(d3.descending)(matrix);
/*//////////////////////////////////////////////////////////
////////////////// Draw outer Arcs /////////////////////////
//////////////////////////////////////////////////////////*/
var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var g = svg.selectAll("g.group")
.data(chord.groups)
.enter().append("svg:g")
.attr("class", function(d) {
return "group " + NameProvider[d.index];
});
g.append("svg:path")
.attr("class", "arc")
.style("stroke", function(d) {
return fill(d.index);
})
.style("fill", function(d) {
return fill(d.index);
})
.attr("d", arc)
.style("opacity", 0)
.transition().duration(1000)
.style("opacity", 0.4);
<!-- language: lang-css -->
#chart rect {
fill: steelblue;
}
#chart text {
fill: white;
font: 10px Helvetica;
text-anchor: end;
}
<!-- language: lang-html -->
<script src="https://d3js.org/d3.v7.min.js"></script>
<svg id="chart"></svg>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论