我正在尝试编写一个使用两个CVS文件的过渡条形图。我知道这两个文件都正确加载,因为它在控制台中显示第一个文件随页面加载,第二个文件在单击更新按钮时加载。
我真正想尝试的唯一一件事就是将svg select更改为分组,而不是选择所有矩形,以防万一那里发生了什么事情。
此块创建svg元素,引入第一个CSV文件,并将矩形附加到图表上。我唯一想到的可能是问题在函数内部,但是如果我从函数中删除它,如何将数据绑定到它们?
//Creating SVG Element
var chart_w = 1000,
chart_h = 500,
chart_pad_x = 40,
chart_pad_y = 20;
var svg = d3.select('#chart')
.append('svg')
.attr('width', chart_w)
.attr('height', chart_h);
//Defining Scales
var x_scale = d3.scaleBand().range([chart_pad_x, chart_w -
chart_pad_x]).padding(0.2);
var y_scale = d3.scaleLinear().range([chart_pad_y, chart_h -
chart_pad_y]);
//Data-------------------------------------------------------------------
d3.csv('data.csv').then(function(data){
console.log(data);
generate(data); });
function generate(data){
//Scale domains
x_scale.domain(d3.extent(data, function(d){ return d }));
y_scale.domain([0, d3.max(data, function(d){ return d })]);
//Create Bars
svg.select('rect')
.data(data)
.enter()
.append('rect')
.attr('x', function(d, i){
return x_scale(i);
})
.attr('y', function(d){
return y_scale(d);
})
.attr('width', x_scale.bandwidth())
.attr('height', function(d){
return y_scale(d);
})
.attr('transform',
"translate(0,0)")
.attr('fill', '#03658C')
'''
我遇到的结果是一个只有更新按钮的空白窗口。如前所述,我知道正在生成数据,因为我可以在控制台中看到它。
答案 0 :(得分:0)
尝试使用以下内容:
svg.selectAll('rect')
.data(data)
如果使用svg.select
,则只会与找到的第一个元素进行数据绑定。
d3.select(选择器):选择与指定选择器字符串匹配的第一个元素。如果没有元素与选择器匹配,则返回空选择。如果多个元素与选择器匹配,则只会选择第一个匹配的元素(按文档顺序)。例如,要选择第一个锚元素:
如果您检查DOM节点,这应该很清楚。
要解决此问题,请更改代码中的某些内容:
让我们创建一个虚拟提取功能:
(function simulateCSVFetch() {
const data = [1,2,3,4,5];
generate(data);
})();
您还通过使用scaleBand
函数将extent
用于域不完整:
d3.extent():使用自然顺序返回给定可迭代的最小值和最大值。如果iterable不包含可比较的值,则返回[undefined,undefined]。可以指定一个可选的访问器函数,该函数等效于在计算范围之前调用Array.from。
x_scale.domain(d3.extent(data, function(d) { // cant use extent since we are using a scaleBand, we need to pass the whole domain
return d;
}));
console.log(x_scale.domain()) // [min, max]
scaleBand
需要映射整个域
带刻度通常用于具有顺序或分类尺寸的条形图。频段标度的未知值实际上是不确定的:它们不允许隐式域构造。
如果我们继续使用该比例尺,我们将仅获得x比例尺的两个值。让我们使用正确的域修复该问题:
x_scale.domain(data);
最后使用selectAll
创建数据绑定:
svg.selectAll('rect')
.data(data)
.enter()
.append('rect')
.attr('x', function(d, i) {
return x_scale(d);
})
.attr('y', function(d) {
return chart_h - y_scale(d); // fix y positioning
})
.attr('width', x_scale.bandwidth())
.attr('height', function(d) {
return y_scale(d);
})
.attr('fill', '#03658C');
这应该可以解决问题。
完整代码:
var chart_w = 1000,
chart_h = 500,
chart_pad_x = 40,
chart_pad_y = 20;
var svg = d3
.select('#chart')
.append('svg')
.style('background', '#f9f9f9')
.style('border', '1px solid #cacaca')
.attr('width', chart_w)
.attr('height', chart_h);
//Defining Scales
var x_scale = d3.scaleBand()
.range([chart_pad_x, chart_w - chart_pad_x])
.padding(0.2);
var y_scale = d3.scaleLinear()
.range([chart_pad_y, chart_h - chart_pad_y]);
//Data-------------------------------------------------------------------
(function simulateCSVFetch() {
const data = [1,2,3,4,5];
generate(data);
})();
function generate(data) {
console.log(d3.extent(data, function(d) { return d }));
//Scale domains
x_scale.domain(d3.extent(data, function(d) { // cant use extent since we are using a scaleBand, we need to pass the whole domain
return d;
}));
// Band scales are typically used for bar charts with an ordinal or categorical dimension. The unknown value of a band scale is effectively undefined: they do not allow implicit domain construction.
x_scale.domain(data);
y_scale.domain([0, d3.max(data, function(d) {
return d
})]);
//Create Bars
svg.selectAll('rect')
.data(data)
.enter()
.append('rect')
.attr('x', function(d, i) {
return x_scale(d);
})
.attr('y', function(d) {
return chart_h - y_scale(d); // fix y positioning
})
.attr('width', x_scale.bandwidth())
.attr('height', function(d) {
return y_scale(d);
})
.attr('fill', '#03658C');
}
工作中的jsfiddle here