【问题标题】:d3 v4 error: "Unexpected value parsing width attribute." in grouped bar chartd3 v4 错误:“意外的值解析宽度属性。”在分组条形图中
【发布时间】:2016-09-18 12:19:32
【问题描述】:

我正在尝试根据Mike Bostock's great example,使用我自己的数据创建一个 d3(版本 4)分组条形图。我不得不将所有 d3 v3 过时的函数更改为新的 v4 函数(例如d3.scale.ordinal -> d3.scaleOrdinal),但随后出现与矩形条的“宽度”和“x”属性相关的错误:

  • '解析宽度属性时出现意外值 0,0,900。'
  • '解析 x 属性时出现意外值 0,900。'

这里是代码的相关部分:

var x0 = d3.scaleBand()
        .range([0, width])
        .round(true);

var x1 = d3.scaleOrdinal();

var y = d3.scaleLinear()
        .range([height, 0]);

var xAxis = d3.axisBottom()
        .scale(x0);

var yAxis = d3.axisLeft()
        .scale(y);

var svg = d3.select("body").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
      .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

d3.csv("myData.csv", function(error, data) {
      if (error) throw error;

      var yearNames = d3.keys(data[0]).filter(function(key) { return key !== "Unit"; });

      data.forEach(function(d) {
        d.years = yearNames.map(function(name) { return {name: name, value: +d[name]}; });

      });


 x0.domain(data.map(function(d) { return d.Unit; }));
 x1.domain(yearNames).range([0, x0.range()]);
 y.domain([0, d3.max(data, function(d) { return d3.max(d.years, function(d) { return d.value; }); })]);

 svg.append("g")
          .attr("class", "x axis")
          .attr("transform", "translate(0," + height + ")")
          .call(xAxis);

 svg.append("g")
          .attr("class", "y axis")
          .call(yAxis)
        .append("text")
          .attr("transform", "rotate(-90)")
          .attr("y", 6)
          .attr("dy", ".71em")
          .style("text-anchor", "end")
          .text("Population");

 var unit = svg.selectAll(".unit")
          .data(data)
        .enter().append("g")
          .attr("class", "unit")
          .attr("transform", function(d) { return "translate(" + x0(d.Unit) + ",0)"; });

 unit.selectAll("rect")
        .data(function(d) { return d.years; })
        .enter().append("rect")
          .attr("width", x1.range())
          .attr("x", function(d) { return x1(d.name); })
          .attr("y", function(d) { return y(d.value); })
          .attr("height", function(d) { return height - y(d.value); })
          .style("fill", function(d) { return color(d.name); });

   });

这是 csv 数据:

Unit,2012,2013
Comp,54.13809524,52.25
Edu,20.39642857,18.75
Bus,16.3,18.5
SoW,16.08,7
Pharm,45,59
Agr,150.3,122.51
Soc,105.2,112.72
Nat,264.86,277.73
Hum,61.73174603,52.91
Law,14.5,22.33
Dent,27.5,11.5
Med,149.1,147.33
Vet,15,19
Jew,1,0.25
Bra,2.5,4

【问题讨论】:

  • 调试你的代码。缩小发生错误的范围。
  • 您的数据是什么样的? Unit 的链接示例中没有任何内容?
  • @Cheesebaron 感谢您的评论。错误可能在变量 x1.domain 和 .range 中。我只是无法弄清楚到底是什么。

标签: javascript d3.js


【解决方案1】:

您的大部分问题都来自.range() 的错误使用。例如这里:

x1.domain(yearNames).range([0, x0.range()]);

这里:

.attr("width", x1.range())

.range 返回一个数组,这不是你想要的。

此外,您可能不希望 x1 成为 scaleOrdinal 而是 scaleBand。我会这样设置:

  x0.domain(data.map(function(d) {
    return d.Unit;
  }));

  // set a sane bar width
  var barWidth = x0.bandwidth() / yearNames.length,
      barPadding = barWidth * 0.3;

  // set up x1 as a scaleBand with padding
  x1.domain(yearNames).range([barPadding , x0.bandwidth() - barPadding]);
  y.domain([0, d3.max(data, function(d) {
    return d3.max(d.years, function(d) {
      return d.value;
    });
  })]);

Running code here.

【讨论】:

  • 非常感谢!我花了整个周末试图找出导致错误的原因......
猜你喜欢
  • 2019-04-21
  • 2017-05-31
  • 1970-01-01
  • 1970-01-01
  • 2013-07-07
  • 1970-01-01
  • 2019-01-01
  • 1970-01-01
  • 2018-11-27
相关资源
最近更新 更多