我是D3的新手,花了几个小时才找到处理结构化数据的任何事情,但没有积极的结果。 我想使用下面的数据结构创建一个条形图。 条形图(水平)绘制,但仅适用于用户“jim”。
var data = [{"user":"jim","scores":[40,20,30,24,18,40]},
{"user":"ray","scores":[24,20,30,41,12,34]}];
var chart = d3.select("div#charts").append("svg")
.data(data)
.attr("class","chart")
.attr("width",800)
.attr("height",350);
chart.selectAll("rect")
.data(function(d){return d3.values(d.scores);})
.enter().append("rect")
.attr("y", function(d,i){return i * 20;})
.attr("width",function(d){return d;})
.attr("height", 20);
有人能指出我做错了吗?
答案 0 :(得分:93)
当您通过join data selection.data进行选择时,数据数组中的元素数量应与选择中的元素数量相匹配。您的数据数组有两个元素(对于Jim和Ray),但是绑定它的选择只有一个SVG元素。您是在尝试创建多个SVG元素,还是将Jim和Ray的得分都放在同一个SVG元素中?
如果要将两个数据元素绑定到单个SVG元素,可以将数据包装在另一个数组中:
var chart = d3.select("#charts").append("svg")
.data([data])
.attr("class", "chart")
…
或者,使用selection.datum,它直接绑定数据而不计算连接:
var chart = d3.select("#charts").append("svg")
.datum(data)
.attr("class", "chart")
…
如果您想为每个人创建多个SVG元素,那么您需要一个数据连接:
var chart = d3.select("#charts").selectAll("svg")
.data(data)
.enter().append("svg")
.attr("class", "chart")
…
第二个问题是你不应该将d3.values与数组一起使用;该函数用于提取对象的值。假设你每个人想要一个SVG元素(因此,在这个例子中是两个),那么rect的数据就是那个人的相关分数:
var rect = chart.selectAll("rect")
.data(function(d) { return d.scores; })
.enter().append("rect")
…
如果您还没有,我建议您阅读以下教程:
答案 1 :(得分:1)
除了mbostock的正确答案之外,这可能会澄清嵌套方面。
您的数据有2度嵌套。你有一个包含2个对象的数组,每个对象都有一个int数组。如果您希望最终图像反映出这些差异,则需要为每个图像进行连接。
以下是一个解决方案:每个用户都由一个组g
元素表示,每个分数由rect
表示。您可以通过以下几种方式执行此操作:在svg上使用datum
,在每个g
上使用身份功能,或者您可以直接加入g
上的数据。在data
上使用g
更为典型,但这里有两种方式:
在svg上使用数据:
var chart = d3.select('body').append('svg')
.datum(data) // <---- datum
.attr('width',800)
.attr('height',350)
.selectAll('g')
.data(function(d){ return d; }) // <----- identity function
.enter().append('g')
.attr('class', function(d) { return d.user; })
.attr('transform', function(d, i) { return 'translate(0, ' + i * 140 + ')'; })
.selectAll('rect')
.data(function(d) { return d.scores; })
.enter().append('rect')
.attr('y', function(d, i) { return i * 20; })
.attr('width', function(d) { return d; })
.attr('height', 20);
使用组(g
)元素上的数据:
var chart = d3.select('body').append('svg')
.attr('width',800)
.attr('height',350)
.selectAll('g')
.data(data) // <--- attach directly to the g
.enter().append('g')
.attr('class', function(d) { return d.user; })
.attr('transform', function(d, i) { return 'translate(0, ' + i * 140 + ')'; })
.selectAll('rect')
.data(function(d) { return d.scores; })
.enter().append('rect')
.attr('y', function(d, i) { return i * 20; })
.attr('width', function(d) { return d; })
.attr('height', 20);
同样,你不必创建这些g元素,但通过这样做,我现在可以用不同的方式表示用户分数(它们与变换有不同的y),我也可以给它们不同的样式,比如这个:
.jim {
fill: red;
}
.ray {
fill: blue;
}