数据未绑定到d3中的选择

时间:2017-04-11 13:03:09

标签: javascript d3.js svg

我遇到绑定数据的问题,其中数据绑定到某些选择而不绑定到其他选择。

对于上下文,我在csv文件中有一系列行。使用d3,我遍历每一行并为csv文件中的每一行生成一个svg。如下所示。

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

然后我打算使用此选择将<g>元素和一系列<rect>元素绑定到svg选择:

//creating a <g> elements
var vehicleText = svgArea.select("g")
.data(d)
.enter()
.append("g")
.attr("id", function(d) {return "vehicle_" + d.vehicle});

//creating a grouped bar chart
var vehicleBars = svgArea.selectAll("rect")
.data(d.sales)
.enter()
.append("rect")
.attr("class", "vehicleBars")
.attr("id", function (d) {return "vehicle_" + d.vehicle + "_" + d.year})
.attr("width", width / 4)
.attr( "x", function (d){
  return xYears(d.year)
})
.attr("y", function(d){
  return yScale(d.value)
})
.attr("height", function(d) {return height - yScale(d.value)})
.attr("fill", function(d) {return colorScale(d.year)});

问题在于<g>元素没有出现,但<rect>元素尽管使用了完全相同的选择。我一直在想,这可能是我将数据绑定到元素的方式的问题。我到底错在了什么?为什么它绑定了一组元素的数据,而不是绑定它的集合? For reference, here is my code

2 个答案:

答案 0 :(得分:1)

这里有两个主要问题:

  1. svg中已有<g>个元素。因此,输入选择应该选择不存在的内容,而不是select("g"),而不是selectAll("foo")

  2. d是一个对象。但是,data函数只接受三件事:数组,函数或什么都没有。因此,它应该是data([d])

  3. 这个问题#2解释了为什么,正如你所说的......

      

    数据被绑定到某些选择而不是其他选择。

    ...以及console.log(vehicleText.datum())返回Cannot read property '__data__' of null

    的原因

    话虽如此,这是你更新的plunker:https://plnkr.co/edit/igliOTB1eq1k31eQ9nY5?p=preview

    然而,这不是实现你想要的最好的方式,也不是我自己做的最好的方式:请记住,我只回答你的问题,而不是更多。

    PS:请勿使用d作为chartGenerator功能中数据的参数。在D3代码中,d通常用于匿名函数中的第一个参数(数据)。像你一样使用d会增加一些混乱,特别是对于经验丰富的D3编码员。

答案 1 :(得分:1)

您可以直接将属性设置为标签文本。试试这种方式。

  var vehicleText = svgArea.append("g")
    .attr("id", "vehicle_" + d.vehicle); 

  vehicleText.append("text")
    .attr("class", "annotation")
    .attr("dx","4em")
    .attr("dy",height+20)
    .text( d.vehicle);

&#13;
&#13;
var rows = [{
    "vehicle": "Ford F - Series PU",
    "Mar-2016": 65179,
    "Mar-2017": 72089,
    "perc_change": 10.6
  },
  {
    "vehicle": "Chevrolet Silverado PU",
    "Mar-2016": 45009,
    "Mar-2017": 45280,
    "perc_change": 0.6
  },
  {
    "vehicle": "Dodge Ram PU",
    "Mar-2016": 34152,
    "Mar-2017": 36885,
    "perc_change": 8
  },
  {
    "vehicle": "Toyota Camry",
    "Mar-2016": 30942,
    "Mar-2017": 28189,
    "perc_change": -8.9
  },
  {
    "vehicle": "Toyota RAV4",
    "Mar-2016": 27376,
    "Mar-2017": 28116,
    "perc_change": 2.7
  },
  {
    "vehicle": "Honda Accord",
    "Mar-2016": 25571,
    "Mar-2017": 27182,
    "perc_change": 6.3
  },
  {
    "vehicle": "Toyota Corolla / Matrix",
    "Mar-2016": 24183,
    "Mar-2017": 26747,
    "perc_change": 10.6
  },
  {
    "vehicle": "Nissan Rogue",
    "Mar-2016": 22566,
    "Mar-2017": 26629,
    "perc_change": 18
  },
  {
    "vehicle": "Honda CR-V",
    "Mar-2016": 25939,
    "Mar-2017": 25758,
    "perc_change": -0.7
  },
  {
    "vehicle": "Honda Civic",
    "Mar-2016": 25052,
    "Mar-2017": 25303,
    "perc_change": 1
  },
  {
    "vehicle": "Ford Escape",
    "Mar-2016": 20806,
    "Mar-2017": 23012,
    "perc_change": 10.6
  },
  {
    "vehicle": "Chevrolet Equinox",
    "Mar-2016": 19636,
    "Mar-2017": 21600,
    "perc_change": 10
  },
  {
    "vehicle": "Toyota Highlander",
    "Mar-2016": 12742,
    "Mar-2017": 21241,
    "perc_change": 66.7
  },
  {
    "vehicle": "Nissan Altima",
    "Mar-2016": 20573,
    "Mar-2017": 20039,
    "perc_change": -2.6
  },
  {
    "vehicle": "Ford Explorer",
    "Mar-2016": 16690,
    "Mar-2017": 19628,
    "perc_change": 17.6
  },
  {
    "vehicle": "GMC Sierra PU",
    "Mar-2016": 16520,
    "Mar-2017": 18900,
    "perc_change": 14.4
  },
  {
    "vehicle": "Chevrolet Malibu",
    "Mar-2016": 10813,
    "Mar-2017": 18577,
    "perc_change": 71.8
  },
  {
    "vehicle": "Subaru Outback",
    "Mar-2016": 13075,
    "Mar-2017": 17769,
    "perc_change": 35.9
  },
  {
    "vehicle": "Ford Fusion",
    "Mar-2016": 19446,
    "Mar-2017": 17560,
    "perc_change": -9.7
  },
  {
    "vehicle": "Jeep Grand Cherokee",
    "Mar-2016": 17653,
    "Mar-2017": 17230,
    "perc_change": -2.4
  }
];


// Code goes here

//setting the margins
var margin = {
  top: 20,
  right: 20,
  bottom: 20,
  left: 20
}

//setting width and height
var width = 300 - margin.left - margin.right,
  height = 300 - margin.top - margin.bottom;

yearVals = ["Mar-2016", "Mar-2017"]

//ranges
var xVehicles = d3.scaleBand().rangeRound([0, width], .1).paddingInner(0.1);

var xYears = d3.scaleBand().domain(yearVals).range([0, xVehicles.bandwidth()])
  .paddingInner(.1)
  .paddingOuter(5.0);

var yScale = d3.scaleLinear().domain([0, 85000]).range([height, 0]);

var colorScale = d3.scaleOrdinal()
  .range(["#87ceeb", "#00bfff"]);


rows.forEach(function(data) {

  chartGenerator(data)
})

d3.selectAll("svg.barSvg")
  .data(rows)
  .enter()
  .append("text")
  .text(function(d) {
    return d.vehicle;
  })



function chartGenerator(d) {

  d.sales = yearVals.map(function(year) {
    return {
      "vehicle": d.vehicle,
      year: year,
      value: +d[year]
    }
  })

  //create vehicle name
  var vehicle = []
  vehicle["name"] = d.vehicle;


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

  //vehicleText not appended to g element


  //console.log(vehicleText.datum());

  var vehicleBars = svgArea.selectAll("rect")
    .data(d.sales)
    .enter()
    .append("rect")
    .attr("class", "vehicleBars")
    .attr("id", function(d) {
      return "vehicle_" + d.vehicle + "_" + d.year
    })
    .attr("width", width / 4)
    .attr("x", function(d) {
      return xYears(d.year)
    })
    .attr("y", function(d) {
      return yScale(d.value)
    })
    .attr("height", function(d) {
      return height - yScale(d.value)
    })
    .attr("fill", function(d) {
      return colorScale(d.year)
    });

  var vehicleText = svgArea.append("g")
    .attr("id", "vehicle_" + d.vehicle);

  vehicleText.append("text")
    .attr("class", "annotation")
    .attr("dx", width / 4)
    .attr("dy", height + 20)
    .text(d.vehicle);

}
&#13;
/* Styles go here */

body {
  width: 1200px;
}

h2,
h3 {
  font-family: sans-serif;
  padding: 20px 50px 0px 50px;
}

.barSvg {
  background: white;
}

.vehicleData {
  background: grey;
  width: 25px;
  height: 15px;
}

.annotation {
  stroke: black;
  stroke-width: black;
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>

<body>
  <h2>Auto Sales - March 2017</h2>
</body>
&#13;
&#13;
&#13;