将父和嵌套数据与d3.js组合 [英] Combining Parent and Nested Data with d3.js
问题描述
我有这样的数据结构(假设数据结构不可协商):
I have a data structure like this (assume that the data structure is non-negotiable):
data = {
segments : [
{x : 20, size : 10, colors : ['#ff0000','#00ff00']},
{x : 40, size : 20, colors : ['#0000ff','#000000']}
]};
使用 d3.js javascript库,我想绘制四个矩形,每个颜色一个颜色
数组。来自段
数组中每个条目的信息用于绘制与其颜色
数组中的每个颜色对应的矩形。例如,红色和绿色矩形的宽度和高度为10.生成的html应该如下所示:
Using the d3.js javascript library, I'd like to draw four rectangles, one for each color in both colors
arrays. Information from each entry in the segments
array is used to draw the rectangles corresponding to each color in its color
array. E.g., The red and green rectangles will have a width and height of 10. The resulting html should look like this:
<div id="container">
<svg width="200" height="200">
<g>
<rect x="20" y="20" width="10" height="10" fill="#ff0000"></rect>
<rect x="30" y="30" width="10" height="10" fill="#00ff00"></rect>
</g>
<g>
<rect x="40" y="40" width="20" height="20" fill="#0000ff"></rect>
<rect x="60" y="60" width="20" height="20" fill="#000000"></rect>
</g>
</svg>
</div>
我想出了一些代码来实现这一点,但我发现了关于使用数据的部分在数据
中的两个不同级别的嵌套是混乱的,我觉得可能有一个更成熟的方法来完成同样的d3.js。以下是代码(完整示例: http://jsbin.com/welcome/39650/edit ) :
I've come up with some code that accomplishes this, but I found the part about using data from two different levels of nesting in data
to be confusing, and I feel that there might be a more idiomatic way to accomplish the same with d3.js. Here's the code (full example at http://jsbin.com/welcome/39650/edit):
function pos(d,i) { return d.x + (i * d.size); } // rect position
function size(d,i) { return d.size; } // rect size
function f(d,i) { return d.color; } // rect color
// add the top-level svg element and size it
vis = d3
.select('#container')
.append('svg')
.attr('width',200)
.attr('height',200);
// add the nested svg elements
var nested = vis
.selectAll('g')
.data(data.segments)
.enter()
.append('g');
// Add a rectangle for each color
nested
.selectAll('rect')
.data(function(d) {
// **** ATTENTION ****
// Is there a more idiomatic, d3-ish way to approach this?
var expanded = [];
for(var i = 0; i < d.colors.length; i++) {
expanded.push({
color : d.colors[i],
x : d.x
size : d.size });
}
return expanded;
})
.enter()
.append('rect')
.attr('x',pos)
.attr('y',pos)
.attr('width',size)
.attr('height',size)
.attr('fill',f);
是否有更好和/或更习惯的方式来访问来自两个不同级别的数据使用d3.js嵌套数据结构?
感谢 meetamit的回答关闭主意,并使用更常用的d3.js缩进感谢 nautat的回答:
Here's the solution I came up with, thanks to meetamit's answer for the closure idea, and using more idiomatic d3.js indentation thanks to nautat's answer:
$(function() {
var
vis = null,
width = 200,
height = 200,
data = {
segments : [
{x : 20, y : 0, size : 10, colors : ['#ff0000','#00ff00']},
{x : 40, y : 0, size : 20, colors : ['#0000ff','#000000']}
]
};
// set the color
function f(d,i) {return d;}
// set the position
function pos(segment) {
return function(d,i) {
return segment.x + (i * segment.size);
};
}
// set the size
function size(segment) {
return function() {
return segment.size;
};
}
// add the top-level svg element and size it
vis = d3.select('#container').append('svg')
.attr('width',width)
.attr('height',height);
// add the nested svg elements
var nested = vis
.selectAll('g')
.data(data.segments)
.enter().append('g');
// Add a rectangle for each color. Size of rectangles is determined
// by the "parent" data object.
nested
.each(function(segment, i) {
var
ps = pos(segment),
sz = size(segment);
var colors = d3.select(this)
.selectAll('rect')
.data(segment.colors)
.enter().append('rect')
.attr('x', ps)
.attr('y',ps)
.attr('width', sz)
.attr('height',sz)
.attr('fill', f);
});
});
以下是完整的工作示例: http://jsbin.com/welcome/42885/edit
Here's the full working example: http://jsbin.com/welcome/42885/edit
推荐答案
您可以使用closures
You can use closures
var nested = vis
.selectAll('g')
.data(data.segments);
nested.enter()
.append('g')
.each(function(segment, i) {
var colors = d3.select(this)
.selectAll('rect')
.data(segment.colors);
colors.enter()
.append('rect')
.attr('x', function(color, j) { return pos(segment, j); })
// OR: .attr('x', function(color, j) { return segment.x + (j * segment.size); })
.attr('width', function(color, j) { return size(segment); })
.attr('fill', String);
});
这篇关于将父和嵌套数据与d3.js组合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!