附加的条不会在svg元素上绘制

时间:2019-06-10 20:49:49

标签: javascript d3.js

我正在尝试编写一个使用两个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')

'''

我遇到的结果是一个只有更新按钮的空白窗口。如前所述,我知道正在生成数据,因为我可以在控制台中看到它。

1 个答案:

答案 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